Я хочу создать класс в C++ под названием Entity. Этот объект имеет указатель на элемент Vector3D, который является позицией объекта в трехмерном пространстве. Конструктор позволяет передать указатель типа Vector3D в конструктор, так что экземпляр Vector3D создается вне класса.
Поскольку есть указатель на динамически выделенный объект, конструктор копирования и оператор присваивания должны быть перегружены для глубокой копии вектора. Однако, поскольку вектор может быть передан в конструкторе, он также может использоваться в другом месте и поэтому не может быть удален в деструкторе. Но если новый Entity, созданный через конструктор копирования или назначенный с помощью оператора =, класс сущности должен удалить экземпляр вектора, потому что он был создан в классе Entity.
Каков наилучший способ решения таких проблем?
#ifndef ENTITY_H
#define ENTITY_H
#include "Vector3D.h"
class Entity {
public:
Entity(Vector3D*);
Entity(const Entity&);
~Entity();
Entity& operator = (const Entity&);
protected:
Vector3D* vector;
};
#endif
Лучший способ - не использовать указатель на Vector3D
, а принимать его по значению. Если Vector3D
- это то, что я подозреваю (обертка вокруг 3-х поплавков или целых чисел), для его совместного использования не так много преимуществ.
Вы также можете начать больше рассуждать о владении и о бремени уничтожения Vector3D
на клиентском коде (код, который создает Entity
).
Если это не вариант, вы можете использовать std :: shared_ptr.
#include <memory>
struct Vector3D {};
struct Entity {
// Construct from another shared_ptr.
Entity(std::shared_ptr<Vector3D> v) : v_(v) {}
// Assume ownership of 'v'.
Entity(Vector3D* v) : v_(v) {}
// depending on which guarantees we have for sharing the vector
// we can omit checks for null.
const Vector3D& vector() const { return v_.get(); }
Vector3D& vector() { return v_.get(); }
private:
std::shared_ptr<Vector3D> v_;
};
Это прекрасный пример того, где использовать новые интеллектуальные указатели С++ 11. Если предполагается, что клиентский код передает права собственности на Entity
и может использовать его дольше, чем срок службы Entity
, вы используете std::shared_ptr
.
Если вы явно хотите передать право собственности на Entity
, то клиентский код больше не должен использовать вектор после его переноса в Entity
, вы используете std::unique_ptr
.
Если клиентский код должен оставаться единственным владельцем и, таким образом, решить, когда вектор будет удален, вы используете std::weak_ptr
.
См., Например, http://en.cppreference.com/w/cpp/memory для более подробного описания их.
Entity
не является владельцемVector3D
. Если он владеет Vector3D, то он должен иметь свою собственную копию.