感谢您提前帮助。 我正在阅读Scott Meyers撰写的“更有效的C ++”一书,但是在第29项"参考计数"中有一个简单的程序。真让我困惑。 该程序在此处复制:
String::String(const String& rhs): value(rhs.value)
{
++value->refCount;
}
然后代码:
String s1("More Effective C++");
String s2=s1;
我真的很困惑为什么s1和s2都有refCount 2。 我理解的是,由于复制构造函数是通过引用传递给const,在s2 = s1之后,s2.refCount将变为2,而s1.refCount将根本不会改变。 请纠正我!! 再次感谢。
最诚挚的问候。
答案 0 :(得分:3)
value
是一个指针,而const
- ness不会传播到指向的对象,因此refCount
在此处是可变的。
引用计数点是共享相同的对象表示,而不会重新创建它,直到所有引用消失,即引用计数降为零。此时,表示被解除分配。
这对于只读对象非常有用,因此如果其中一个引用实例想要更改该共享表示,则通常会克隆它,并且从一个引用再次开始重新计数。
然后存在使引用计数线程安全的问题。 Sutter对此进行了广泛的撰写,请参阅gotw #43,gotw #44和gotw #45。
答案 1 :(得分:3)
我知道
s2.refCount
将变为2,而s1.refCount
则不会发生变化。
有你的误解。没有s2.refCount
和s1.refCount
这样的动物。相反,变量称为s2.value->refCount
和s1.value->refCount
。请注意s2.value
== s1.value
,因此它们固有地共享相同的refCount
成员。
答案 2 :(得分:1)
如果s1
使用的引用计数为1,那么当它死亡时它将删除该字符串。请考虑以下事项:
String s2;
{
String s1("More Effective C++");
s2 = s1;
} // A
在A点,s1
死亡。如果其引用计数为1,则会清除与s2
共享的存储空间,s2
将使用无效存储空间。
引用计数与每个对象无关。正如您从我给出的示例中看到的那样,这将毫无价值,因为引用计数永远不值得信赖,因为它可以作为清除安全的指标。
引用计数与这些对象共享的存储块相关联。 s1
和s2
只有一个引用计数。两者共享一块带有“更有效的C ++”的存储空间。这意味着有两个对该存储的引用。两者中的每一个都需要知道有两个,这样他们就不会清理另一个正在使用的存储。
答案 3 :(得分:0)
引用计数必须驻留在单独的共享内存中:
struct Foo
{
unsigned int * refcount; // shared among all "equal" objects!
Foo() : refcount(new auto {1U}) { }
Foo(Foo const & rhs) : refcount(rhs.refcount) { ++*refcount; }
~Foo() { --*refcount; if (*refcount == 0) { delete refcount; } }
Foo & operator=(Foo const & rhs)
{
if (this == std::addressof(rhs)) { return *this; }
--*refcount;
if (*refcount == 0) { delete refcount; }
refcount = rhs.refcount;
++*refcount;
return *this;
}
// etc.
};
答案 4 :(得分:0)
value
是指向底层实现结构的指针。字符串复制构造函数将指针复制到新对象(s2
)中,并递增指向实现结构的引用计数。但是,请记住原始对象(s1
)具有相同的指针,因此从s1看到的引用计数也会增加。只有一个底层实现结构,因此从一个String对象对其进行操作会影响共享该实现结构的所有其他String对象。这就是整个引用计数点!