不可变的数据结构或const变量?

时间:2013-05-12 03:24:13

标签: c++ copy

当我编写一个类时,无论是使用不可变类还是只使用 const关键字,总是一个大问题。

我来自Objective-C,当我使用Objective-C时,存在分离的可变/不可变约定。这主要是因为在C ++中缺少const语义,但它也保证了对象的不变性,特别是当不可变对象被复制到可变对象时我可以陷阱。所以我可以将共享状态用于不可变对象,并且仅在将状态复制到可变对象时才复制状态。

在C ++中,有const语义,所以我尝试用它设计一个容器,但我有一些问题。这是示例代码。

struct Foo
{
  int bar;
};

Foo const f1;
Foo f2 = f1;    // This is allowed but...

允许将f1复制到f2,并且不会发出任何警告或错误。问题是我无法捕获将不可变对象复制到可变对象的情况。当我编写一个复制赋值构造函数时,它适用于可变或不可变对象。我想让不可变对象使用共享状态,只有在将它复制到可变对象时才会被复制。

写入时复制不适合我,因为我的容器代码应该适合实时程序。必须看到性能命中,并且位置应该是可预测的。不允许写入时复制,因为它将复制成本推迟到不可预测的时间点。复制成本必须可见。

这可以通过为每个不可变/可变对象创建分隔对象来解决,但我不确定这是C ++上的好设计。

使用可见复制成本制作不可变/可变类的推荐模式是什么?我认为如果我可以将一些复制构造函数从immutable变为可变,这可以解决,但我找不到任何方法。

1 个答案:

答案 0 :(得分:1)

使用指针:

const Foo *f1 = new Foo(); /* Foo instance is trapped in pointer-to-const */
//Foo *f2 = f1; /* Error; not allowed without cast. */
Foo *f3 = new Foo(*f1); /* Use copy constructor */
delete f1;
delete f3;

使用shared_ptr(C ++ 11):

#include <memory>

std::shared_ptr<Foo> f1 = std::make_shared<Foo>(); /* shared_ptr will not implicitly copy object */
std::shared_ptr<Foo> f2 = f1; /* No copy made */
std::shared_ptr<Foo> f3 = std::make_shared<Foo>(*f1); /* use copy constructor */

如果客户端直接使用该对象,则他们负责复制开销。这或多或少是预期的。您可以通过在类中内部使用指针/ refcounting / copy-on-write来隐藏开销,但正如您所说,这不是您想要的。