C++ 为什么在这种情况下调用r值引用构造函数?

C++ 为什么在这种情况下调用r值引用构造函数?,c++,return,implicit-conversion,C++,Return,Implicit Conversion,为什么输出不正确 A(B &&) ? 此代码是否与复制省略有任何关系?(但是A和B是不同的类型,因此复制省略在这里不应该起作用)返回为右值规则因应C++14发布前的审查而更改。该变更是在该过程的后期添加的,并由,其修订了12.8/32,措辞如下: 或者,当return语句中的表达式是一个id表达式(可能带括号),该表达式命名了一个对象,并在主体中声明了自动存储持续时间 这意味着,现在返回任何局部变量都会将该变量指定的对象视为一个右值(如果重载解析失败,请重试) 由于CWG问题被

为什么输出不正确

A(B &&)
?


此代码是否与
复制省略
有任何关系?(但是A和B是不同的类型,因此
复制省略
在这里不应该起作用)

返回为右值规则因应C++14发布前的审查而更改。该变更是在该过程的后期添加的,并由,其修订了12.8/32,措辞如下:

或者,当
return
语句中的表达式是一个id表达式(可能带括号),该表达式命名了一个对象,并在主体中声明了自动存储持续时间

这意味着,现在返回任何局部变量都会将该变量指定的对象视为一个右值(如果重载解析失败,请重试)


由于CWG问题被认为是语言中的一个缺陷,编译器甚至可以在“C++11模式”下实现这个新规则。缺陷的关键在于“它总是以这种方式工作”,因此严格来说,这不是C++11和C++14之间的变化,而是C++11的含义在2014年被修改。

复制省略与a相关,而不是在get()堆栈框架中构造。 所发生的是,返回的
b
(这是临时的,因为“因为返回而死亡”:这是从C++14开始的),用于在主堆栈框架中构造省略的
A


由于临时对象绑定了r值引用,这就是您观察到的。

这实际上是一个非常有趣的问题。我发现12.8/32中的措辞有些不清楚:不清楚返回表达式的类型是否必须与函数的返回类型相同才能应用规则。我认为您可以阅读它,就好像任何具有自动存储的返回对象都被视为由右值指定一样。不同的编译器。此处似乎相关。@KerrekSB根据(31.1),
当表达式是非易失性自动对象(函数参数或处理程序(15.3)的异常声明引入的变量除外)的名称,该对象的类型(忽略cv限定)与函数返回类型相同时
,我认为
相同类型
必须与
返回类型
完全相同。这意味着如果我返回一个
a
对象,
copy elision
将起作用。但是从
B
A
的隐式转换发生在
copy elision
之前,
copy elision
不应该影响
隐式转换。这不是问题所在,但除非您需要额外的东西,否则不要使用
std::endl
<代码> \n′/COD>结束一行。我在哪里可以找到ISO C++标准中的语句(现在,N45 94)?但是,在执行<代码>拷贝删除< /代码>之前有一个隐式转换。要点是B,因为返回,被认为是暂时的,因此被绑定和转换。该语句可以在N494} 12.8 32中找到。我认为只有当
拷贝省略
被满足时才有效@凯撒:是的,过去就是这样。但相关的核心问题是“如果它也能更普遍地发挥作用,那就太好了”,然后有一个国家机构的评论改变了这一点,所以它被改变了。链接的问题包含一个与你非常相似的激励示例。@Caesar是的,我每次读到这个时都会犯这个错误。这是一个非常复杂的句子。但是这样想吧。如果您按名称返回一个自动存储变量,那么从中移动肯定是安全的,那么为什么不让语言自动为您这样做呢?@Barry实际上,我不喜欢“太聪明”的编译器。haha@Caesar:对不起,我错了,你说的是对的-如果你明确删除,那么程序确实是错误的。所以事实上,叮当声是错误的,这是一个已知的错误。只有当隐式定义的移动构造函数被选中并被删除时,重载解析才会失败,并作为左值重试。
A(B &&)
A(const B &)