C++;:作为引用或指针的基类型成员变量 我想知道什么是最好的方法来实现一个设计困境在C++ +…/P>
我有一个类,它包含另一个类的C++;:作为引用或指针的基类型成员变量 我想知道什么是最好的方法来实现一个设计困境在C++ +…/P>,c++,inheritance,class-members,C++,Inheritance,Class Members,我有一个类,它包含另一个类的Base类型的成员变量,创建的真实对象被创建为Base的派生的 类不需要修改这些变量,它只使用它们。其他人正在创建这些变量。这些派生的类还需要转到我的类中的容器(std::vector、QList等)类,因此它们应该执行适当的拷贝构造和赋值 所以,我想知道什么可能是最好的: 将成员变量创建为Base*,让我们来管理它们和它们使用的内存。这导致了经典的内存泄漏问题。。。有人只是忘记删除对象,当他们不再使用它了 将成员变量创建为基&,让我们祈祷它们在超出范围时不会消失 你
Base
类型的成员变量,创建的真实对象被创建为Base
的派生的
类不需要修改这些变量,它只使用它们。其他人正在创建这些变量。这些派生的
类还需要转到我的类中的容器(std::vector、QList等)类,因此它们应该执行适当的拷贝构造和赋值
所以,我想知道什么可能是最好的:
将成员变量创建为Base*
,让我们来管理它们和它们使用的内存。这导致了经典的内存泄漏问题。。。有人只是忘记删除对象,当他们不再使用它了
将成员变量创建为基&
,让我们祈祷它们在超出范围时不会消失
你应该考虑所有权。谁拥有这些东西?如果这个问题没有明确的答案,您应该使用std::shared\u ptr
(共享所有权)。如果有一个类拥有该对象,而其他所有类都只使用它们,那么您可以使用std::unique_ptr
,一个指针容器,如boost::ptr_vector
,或者如果没有多态性,则表示只拥有具体实例的类。在所有其他类中,可以使用指向该对象的普通指针(首选为类成员)或引用(首选为参数,如果不允许null)
案例1——共有所有权
class IWorkOnBaseObjects
{
std::vector<std::shared_ptr<Base>> mySubset;
};
class MeToo
{
std::shared_ptr<Base> iNeedThisOne;
};
类IWorkOnBaseObjects
{
std::向量mySubset;
};
梅托级
{
std::共享\u ptr在该电话中;
};
案例2
class HomeOfBaseObjects
{
std::vector<std::uniqe_ptr<Base>> baseObjects;
};
class IWorkOnBaseObjects
{
std::vector<Base*> mySubset;
};
类对象
{
矢量基对象;
};
类IWorkOnBaseObjects
{
std::向量mySubset;
};
案例3
class A : public Base{};
class B : public Base{};
class HomeOfAObjects
{
std::vector<A> aObjects;
};
class HomeOfBObjects
{
std::vector<B> bObjects;
};
class INeedABaseObject
{
Base* thisOne;
};
A类:公共基{};
B类:公共基{};
类对象
{
std::向量对象;
};
类对象
{
std::向量对象;
};
类IneedBaseObject
{
基*这个;
};
拥有引用成员变量总是一个糟糕的选择,因为编译器生成的赋值和移动赋值做了错误的事情,或者不是人们所期望的那样
对于成员变量,请坚持使用指针或智能指针。我会使用指针,无论是对于向量(即向量
,而不是向量
),还是容器类,原因如下:
- 如果将派生对象存储在向量中,该向量可能会被重新调整大小,从而导致所有对象“移动”到内存中的新位置。这将使所有未完成的指针和引用无效
- 如果您的容器包含引用,您将无法像复制包含指针的容器那样轻松地复制它,因为引用只能在定义时绑定(因此在构造函数中通过
MyClass::MyClass(int&a):memberA(a){}
,如果内存可用)
- 指针可以根据需要通过其他方式(如set方法)进行更改,并且在缺少信息的情况下可以设置为null
就所有权而言,jrok首先说:shared\u ptr
是你的朋友。不要重新发明轮子,只要利用标准库为您简化事情即可。在这种情况下,你唯一需要担心的是循环指针(即,对象指向自身,所以总是有一个有效的指针)。(不是派生的
,这个类将有一个数据成员,它是指向基的指针或引用)需要值语义(这是另一种说法,“正确地复制和赋值”)
如果是这样的话,那么引用成员变量几乎是不可能的,因为它们不能被重置。在有些奇怪的情况下,您仍然可以使用它们,但您也可以假设您不会使用它们,并使用指针
引用数据成员有时对具有“实体语义”的类型有用(即,它们根本不赋值,也可能不复制),但它们仍然不能给您带来太多好处。它们还可以引诱您编写一个构造函数,该构造函数接受const Base&
参数,并将其存储在引用数据成员[*]中
谁拥有对象(并负责释放对象)完全独立于您是使用指针还是引用。对于您拥有的对象,可能有一个不使用引用的通用约定(应该有一个惯例,不要对你拥有的东西使用原始指针,你应该选择或编写一个合适的智能指针。智能指针类可以保存一个原始指针)。但这只是惯例。你不应该假设只有当你有一个指针时才管理内存
小结:使用指针,然后单独决定如何管理内存
[*]这是一个错误,因为最终会有人意外地在初始值设定项中使用临时对象,然后您的类及其引用数据成员的实例将比临时对象更长寿。因此,存储引用以供返回后使用的对象不应使用常量&
参数,即使它们不修改对象。他们可以使用常量*
来代替。在C++11中,我想如果还有一个右值引用重载,可以避免为临时对象选择常量和重载,但这不是我已经尝试过的。如果你在控制对象的生存时间方面有问题,Hansmad是正确的您应该与创建或管理它的人共享它的所有权。
您有两个选项:
1) boost::shared_ptr
或std::tr1::shared_ptr
你可以很容易地使用f类
boost::shared_ptr<Base> sharedObject( new Drived() );
boost::shared_ptr<Base> validCopy( sharedObject ); // Ok share ownership
Base* p = sharedObject.get();
boost::shared_ptr<Base> invalidCopy( p ); // Error, can't create new shared_ptr from raw pointer