我是C ++的新手,我正在努力寻找经常发现的语句(例如在http://yosefk.com/c++fqa/ref.html#fqa-8.1中),与指针相反,在初始化之后,你无法为另一个对象创建一个引用点。
我在这里有一个代码片段,在我看来,这完全是这样的:
std::string s1("Hello");
std::string s2("World");
std::string& refToS = s1; // initialize reference to object 1
cout << refToS << endl;
refToS = s2; // make reference point to object 2
cout << refToS << endl;
输出为“Hello World”。
这可能是一个枯燥的问题,但我无法弄清楚我的误解是什么。
答案 0 :(得分:2)
您所做的就是将s2
分配给s1
,refToS
仍指代s1
。
std::string s1("Hello");
std::string s2("World");
std::string& refToS = s1; // initialize reference to object 1
cout << refToS << endl;
refToS = s2; // assign s2 to the referent of refToS
cout << refToS << endl;
cout << s1 << endl;
cout << s2 << endl;
输出
Hello
World
World
World
答案 1 :(得分:0)
refToS = s2; // make reference point to object 2
此行不符合您的想法。这就像发生s2
到s1
的任务一样。
您无法更改引用所指向的对象。
答案 2 :(得分:0)
引用是它引用的对象。所以这段代码:
refToS = s2;
不符合您的想法。它实际上将s2
分配给refToS
个引用(即`s1)。所以,这一行实际上是这样做的:
s1 = s2;
执行后,s2
和s1
都将等于“世界”
答案 3 :(得分:0)
虽然John已正确解释您实际上正在string::operator=(const string&)
上调用s1
,但更改s1
并未重新引用该引用,我认为重要的是要指出FQA在这里是错误的。
可以将参考点指向另一个对象,即创建引用时甚至不存在的对象。
C ++标准具有以下规则:
如果在对象的生命周期结束之后,在重用或释放对象占用的存储之前,在原始对象占用的存储位置创建一个新对象,指针 指向原始对象,引用原始对象的引用,或者原始对象的名称将自动引用新对象,并且一旦生命周期为新对象已经开始,可以 用于操纵新对象,如果:
- 新对象的存储空间正好覆盖原始对象占用的存储位置, 和
- 新对象与原始对象的类型相同(忽略顶级cv限定符),
- 原始对象的类型不是const限定的,如果是类类型,则不包含任何类型为const-qualified或引用类型的非静态数据成员,并且
- 原始对象是类型为
T
的派生程度最高的对象,新对象是类型为T
的派生程度最高的对象(即,它们不是基类子对象)。
简单来说,这意味着引用绑定到特定的内存位置,不能反弹到另一个内存位置。但是该内存位置的对象可以更改(一个的结束生命周期,开始另一个的生命周期),以便相同的引用可以访问多个不同的对象。
要做到这一点,请使用显式的析构函数调用(结束对象的生命,但释放内存),然后使用placement-new:
refToS.~string();
// refToS now refers to raw storage
new (&refToS) std::string("Creating a new string");
这与在s1
上使用赋值运算符不同,结果是一个全新的std::string
对象。
显然,说“参考是对象”是一种误解。此声明在概念上错误的另一个证据是,当对象超出范围时,析构函数会运行。当引用超出范围时,没有任何反应。引用是在初始化期间绑定到内存位置的句柄(就像const
指针一样),并且作为句柄,它与对象本身不同。