C++ 关于引用计数的困惑
谢谢你提前帮忙。 我正在读Scott Meyers更有效的C++,但在第29项“引用计数”中的一个简单程序真的让我困惑。 程序复制到此处:C++ 关于引用计数的困惑,c++,reference,effective-c++,C++,Reference,Effective C++,谢谢你提前帮忙。 我正在读Scott Meyers更有效的C++,但在第29项“引用计数”中的一个简单程序真的让我困惑。 程序复制到此处: String::String(常量字符串和rhs):值(rhs.value) { ++值->引用计数; } 然后编码: String s1("More Effective C++"); String s2=s1; 我真的很困惑为什么s1和s2都会有一个refCount 2。 我的理解是,由于复制构造函数是通过引用传递给const的,因此在s2=s1之后,s
String::String(常量字符串和rhs):值(rhs.value)
{
++值->引用计数;
}
然后编码:
String s1("More Effective C++");
String s2=s1;
我真的很困惑为什么s1和s2都会有一个refCount 2。
我的理解是,由于复制构造函数是通过引用传递给const的,因此在s2=s1之后,s2.refCount将变为2,而s1.refCount将不会发生任何变化。
请纠正我!!
再次感谢
致以最诚挚的问候。如果
s1
使用的引用计数为1,则它将在字符串终止时取下该字符串。考虑以下事项:
String s2;
{
String s1("More Effective C++");
s2 = s1;
} // A
在点A处,s1
死亡。如果它的refcount为1,它将清理它与s2
共享的存储,并且s2
将使用无效存储
引用计数不与每个对象关联。正如您从我给出的示例中看到的,这将是毫无价值的,因为引用计数永远不会作为安全清理的指标
引用计数与这些对象共享的存储块相关联。
s1
和s2
只有一个引用计数。两者共享一块存储空间,其中包含“更有效的C++”。这意味着有两个对该存储块的引用。这两个函数中的每一个都需要知道有两个,这样它们就不会清理另一个正在使用的存储。value
在本例中是一个指针,并且const
-ness不会传播到所指向的对象,因此refCount
在这里是可变的
引用计数的要点是共享相同的对象表示,而不重新创建它,直到所有引用消失,即引用计数降至零。此时,表示将取消分配
这对于只读对象非常有效,所以如果引用实例之一想要更改共享表示,通常会对其进行克隆,并且引用计数会从一开始重新开始
然后,使引用计数线程安全存在一些问题。萨特对此进行了大量的写作,参见,和
我知道s2.refCount
将变为2,而s1.refCount
将不会改变
这是你的误解。没有像
s2.refCount
或s1.refCount
这样的动物。相反,这些变量被称为s2.value->refCount
和s1.value->refCount
。请注意,s2.value
==s1.value
,因此它们本质上共享相同的refCount
成员。引用计数必须驻留在单独的共享内存中:
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.
};
value
是指向底层实现结构的指针。字符串复制构造函数将指针复制到新对象(s2
)中,并增加指向实现结构的引用计数。但是,请记住,原始对象(s1
)具有相同的指针,因此从s1看到的引用计数也将增加。只有一个底层实现结构,因此从一个字符串对象对其进行操作会影响共享该实现结构的所有其他字符串对象。这就是整个参考点计数 我很高兴您的示例Foo
没有实际资源可供共享。这将使此赋值运算符看起来非常简单。;)