考虑:
#include <string>
#include <iostream>
class Foo
{
public:
Foo( char const * msg ) : x( y )
{
y = msg;
}
std::string const & x;
private:
std::string y;
};
int main( int argc, char * argv[] )
{
if ( argc >= 2 )
{
Foo f( argv[1] );
std::cout << f.x << std::endl;
}
}
这会编译并打印出第一个参数......但我怀疑它是否真的&#34;合法&#34; /格式良好。我知道初始化列表应该按照它们在类中声明的顺序初始化变量,以免你引用尚未初始化的变量。但是成员变量不在初始化列表中呢?我可以安全地创建对它们的展示吗?
(当然,这个例子毫无意义。只是为了澄清我在谈论的内容。)
答案 0 :(得分:21)
你可以这样做 1 因为:
x
和y
都在范围内([basic.scope.class]/1)。y
的{{1}}存储空间,因此该引用可以绑定到y
}。在构造函数的复合语句中使用该引用(在成员初始化完成后)也没问题。这是因为y
被认为是初始化的,x
现在指的是生命周期已经开始的对象。
<子> 1 - 对于语言律师来说,这是一个警告。从技术上讲,引用需要绑定到有效对象([basic.life]/7),这意味着它的生命周期已经开始。但是,就像[dcl.ref]/5详细信息一样,预计会有效!有问题的措辞和可能的解决方案在Core Language issue 363中讨论(由@ T.C。在删除的评论中提供)。标准中存在一个错误,但您的代码意图很好,并且实现通常都会意识到它。 子>
答案 1 :(得分:3)
但是不在初始化列表中的成员变量呢?
变量是否在初始化列表中,在这方面无关紧要。如果变量不在初始化列表中(也没有默认成员初始值设定项),则默认初始化。
y
在x
之后初始化。这不是因为成员初始化列表,因为成员初始化列表不会影响成员初始化的顺序。成员按其声明的顺序初始化。
但是,y
是否已初始化也无关紧要。它很好地在成员初始化之前将引用绑定到成员(除了绑定到未初始化成员的虚拟基础;这将具有UB)。
关于安全性(或者更准确地说正确性),我建议您花些时间考虑复制Foo
时会发生什么。 x
会引用什么?那是班级用户所期望的吗?
答案 2 :(得分:0)
我可以安全地创建对它们的展示吗?
是的,你可以。无论是否初始化,成员y
的存储地址都是已知的,因此x(y)
引用初始化是合法的。