C++ 初始化右值引用成员
我试图在以下情况下初始化右值引用成员:C++ 初始化右值引用成员,c++,C++,我试图在以下情况下初始化右值引用成员:struct a是聚合,而class B具有用户定义的构造函数,因此它不是聚合。根据这里的说法, 结构A{ int&r; }; A a1{7};//好的,生命周期延长了 A a2(7);//格式良好但悬而未决的引用 my结构A中的引用应该正确初始化,临时字符串应该扩展,但不是这样。 对于我的B类,在同一参考页中: 与构造函数初始值设定项列表中引用成员的临时绑定仅在构造函数退出之前持续存在,而不是只要对象存在。(注意:截至1696年DR,此类初始化的格式不正
struct a
是聚合,而class B
具有用户定义的构造函数,因此它不是聚合。根据这里的说法,
结构A{
int&r;
};
A a1{7};//好的,生命周期延长了
A a2(7);//格式良好但悬而未决的引用
my结构A
中的引用应该正确初始化,临时字符串应该扩展,但不是这样。对于我的
B类
,在同一参考页中:
与构造函数初始值设定项列表中引用成员的临时绑定仅在构造函数退出之前持续存在,而不是只要对象存在。(注意:截至1696年DR,此类初始化的格式不正确)。
(直到C++14)
但是我仍然对MSVC的/std:c++最新版本有问题。我遗漏了什么吗
结构A
{
std::string&&ref;
};
B类
{
std::string&&ref;
公众:
B(std::string&&rref):ref(std::move(rref)){
void print(){std::cout您的类A
是聚合类型,但B
不是,因为它有一个用户提供的构造函数和一个私有非静态成员
因此,A{std::string{“hello world”};
是聚合初始化,它通过将引用绑定到A
的引用来延长临时的生存期
另一方面,B
不是聚合初始化。它调用用户提供的构造函数,传递引用。传递引用不会延长临时对象的生存期。当B
的构造函数退出时,std::string
对象将被销毁
因此,a
的后续使用具有明确定义的行为,而b
的后续使用将具有未定义的行为
<>这是C++ 11以来所有C++版本的(在程序之前明显不正确)。
如果您的编译器正在为a
打印垃圾(从程序中删除b
后,使其不再具有未定义的行为),则这是编译器中的错误
关于问题的编辑:
无法通过绑定到非聚合类的引用成员来延长临时类的生存期
依赖这个生命周期扩展是非常危险的,因为如果将来碰巧使类成为非聚合类,则很可能不会得到任何错误或警告
如果希望类始终保留对象直到其生命周期结束,则只需按值而不是按引用存储它:
class B
{
std::string str;
public:
B(std::string str) : str(std::move(str)) {}
void print() { std::cout << str << '\n'; }
};
B类
{
std::字符串str;
公众:
B(std::string str):str(std::move(str)){}
空打印(){STD::CUT:引用不支持你的代码< >代码> A1 { 7 };延长临时的生命。<代码> /STD:C++最新不指定C++标准(这可能与这个问题非常相关)最新的C++版本依赖于MSVC版本。如果可以指定C++版本,则最好避免引用成员。这对于RValk引用来说是双重的,因为它们在类中不延长临时的生存期。members@HolyBlackCat它是新的C++20括号内的聚合初始化语法.GCCtrunk已经支持它:@NathanOliver你能为右值引用提供一个引用吗?当它们是类成员时,不延长临时变量的生存期吗?1.删除b
后,MSVC仍然打印垃圾。(实际上它打印的是一个空行。)无论使用default
还是c++14 17或最新版本。2.为什么初始化b
不会延长临时文件的生命周期?3.使用b()默认初始化b如何:ref(std::string{“hello world”}{}
?@szppeter在初始化b
时,临时变量首先绑定到构造函数参数中的引用,该参数将其生存期“延长”到包含构造函数调用的完整表达式结束。但是将另一个引用绑定到临时变量不会进一步延长生存期。使用b()进行初始化:ref(std::string{“hello world”}{}
是您问题中的引号所指的内容。它自C++14以来格式不正确,在此之前没有将生存期延长到构造函数调用的持续时间之外。引号是直到C++14
,而不是因为C++14
@szppeter它是“直到C++14”,因为C++14将引用绑定到成员初始值设定项列表中的临时值是格式不正确的,所以谈论它是否延长临时生存期不再有意义。另请参见。@walnut伟大的答案。我可以问一下:在a
(类型a
)的情况下是由临时文件的聚合初始化形成的,临时文件的生存期是否仍由堆栈控制?是否可以从函数返回并使用(的副本)a
?