虽然 John 正确解释了您实际上是在调用string::operator=(const string&)
,s1
更改s1
而不是重新绑定引用,但我认为重要的是要指出 FQA 在这里是错误的。
可以将引用指向不同的对象,该对象在创建引用时甚至不存在。
C++ 标准有以下规则:
如果在一个对象的生命周期结束之后并且在对象占用的存储空间被重用或释放之前,在原始对象占用的存储位置创建一个新对象,一个指向原始对象的指针,一个指向原始对象的引用引用原始对象,或者原始对象的名称将自动引用新对象,并且一旦新对象的生命周期开始,可用于操作新对象,如果:
- 新对象的存储恰好覆盖了原始对象占用的存储位置,并且
- 新对象与原始对象的类型相同(忽略顶级 cv 限定符),并且
- 原始对象的类型不是 const 限定的,并且,如果是类类型,则不包含其类型为 const 限定或引用类型的任何非静态数据成员,并且
- 原始对象是类型派生度最高的对象,
T
而新对象是类型派生度最高的对象T
(也就是说,它们不是基类子对象)。
用简单的英语来说,这意味着一个引用被绑定到一个特定的内存位置,并且不能被反弹到另一个内存位置。但是该内存位置的对象可以更改(一个的结束生命周期,另一个的开始生命周期),以便同一个引用可以访问多个不同的对象。
为此,请使用显式析构函数调用(结束对象的生命,但释放内存)然后放置新的:
refToS.~string();
// refToS now refers to raw storage
new (&refToS) std::string("Creating a new string");
这与在 上使用赋值运算符不同s1
,结果是一个全新的std::string
对象。
显然,说“引用是对象”是一种误解。这个陈述在概念上是错误的另一个证明是当对象超出范围时,析构函数运行。当引用超出范围时,什么都不会发生。引用是在初始化期间绑定到内存位置的句柄(就像const
指针一样),并且作为句柄,它与对象本身不同。