我应该通过引用,值或ptr存储完全封装的成员吗?

时间:2012-03-02 09:58:24

标签: c++ coding-style private-members

所以我有一个标准的C ++设置,其中包含一个存储另一个对象的对象。存储的对象完全拥有,它永远不会泄露到外面。该成员是非const。

class Container
{
private:
    Contained item;
}

据我所知,当我的Container被实例化时,将在item成员上调用默认构造函数,我不必在初始化列表中管理它。 我还能正确理解当我的对象被销毁时,item上的dtor会被自动调用吗?

另一种选择是通过参考当然存储它

class Container
{

private:
    Contained& item;

public:

    Container() : Contained()
    {

    }
}

在这种情况下,我不知道我是否应该在dtor中delete

另一种选择是通过ptr存储它

class Container
{
private:
    Contained* item;
public:
    Container()
    {
        item = new Contained();
    }

    ~Container()
    {
        delete item;
    }
}

知道我的item永远不会返回给调用者并且永远不会流入外部API而永远不会被重新分配,最好的方法是什么?正如我所提到的,item成员不是const (这将是一个自我调整大小的数据结构)。

5 个答案:

答案 0 :(得分:2)

最简单的方法是存储对象本身。我想说,为此目的使用参考是令人困惑的。使用指针的一个优点是,您可以避免在头文件中定义Contained类型 - 您可以改为转发declare Contained,并将所有详细信息保存在.cpp文件中。

答案 1 :(得分:1)

第一种方式是我认为最好的方式(看起来你不需要对象进行懒惰构建)。第二种方式要求你从外部传入对象并保证它的生命周期,第三种方法实际上只有你想要延迟实例化(即只在第一次使用时创建对象)。

答案 2 :(得分:1)

在这种情况下,最好存储对象本身,是的。通过引用存储它只会为对象创建别名,因此您的类不是实际的所有者。通过指针存储是没用的,除非您的对象是基类,并且您可能想要存储派生对象。

答案 3 :(得分:0)

与Luchian Grigore相反,我会选择指针/引用方法:将封装对象存储为引用或指针允许您向前声明它,从而节省编译时间。

除此之外,它还允许您拥有init()destroy()成员函数,这些函数将依次调用封装对象的构造函数和析构函数,以及执行其他部分的初始化。宾语。这样,可以通过init()的返回值来处理错误的初始化。

答案 4 :(得分:0)

大多数情况下,您希望减少对类的依赖性。如果这个类构成了界面的一个组成部分(即使该成员是私有的),那么你可以假设使用你的类的任何人都将使用这个。

在这种情况下,将其作为成员变量是有道理的。

如果它是您的类的实现细节,您应该使用前向声明从用户隐藏此详细信息,因此请使用允许前向声明的类型。

它不太可能成为参考。必须在构造类时初始化引用,因此构造函数可能必须传入它引用的对象。用新的和解除引用来声明它会导致混乱。

如果它是一个指针,那么你的类可以使用析构函数来管理它的生命周期。在这种情况下,我经常使用原始指针,因为它很好地受到控制,我的析构函数可以愉快地删除它,假设我的类是不可复制的。

如果使用shared_ptr,则可以使用前向声明。但要注意你的语义现在是,如果你复制你的对象,所有的副本将有一个指向同一个底层对象的指针。如果这不是你想要的,shared_ptr可能是错误的。此外,如果在类不可复制时使用shared_ptr,则不会真正共享它。

因此,除非你能使用允许前向声明的unique_ptr,否则我会选择原始指针和不可复制的类。

如果你的成员确实仍然是一个实现细节但是非常标准的东西,比如地图或向量,那么在使用前向声明的范围内,不值得“封装它”,只包含其中包含的类型地图或矢量,但不是地图或矢量本身。