【发布时间】:2017-08-08 06:52:36
【问题描述】:
看看这段代码:
#include <stdio.h>
struct Foo {
Foo() { }
Foo(const Foo &) { printf("copy\n"); }
Foo(Foo &&) { printf("move\n"); }
};
Foo getFoo() {
Foo f;
return *&f;
}
int main() {
getFoo();
}
C++14 标准规定 (12.8/31) 允许复制/移动省略:
在具有类返回类型的函数的返回语句中,当 表达式是非易失性自动对象的名称(除了 一个函数或 catch 子句参数)具有相同的 cv-unqualified type 作为函数返回类型,可以进行复制/移动操作 通过将自动对象直接构造到 函数的返回值
在我的示例中,返回表达式不是名称,因此我认为不允许省略。
我检查了 GCC/clang/MSVC,虽然 clang/MSVC 没有忽略副本,但 GCC 可以。 GCC在这里违反标准吗?
【问题讨论】:
-
好吧,我不明白为什么编译器会保留多余的
*和&运算符。另外,您使用的是哪个版本的编译器?你是在 C++14 模式下构建的吗?另外,在引用标准时,请注明代码出处(名称或章节/章节编号)。 -
在一个完全不相关的注释上,你为什么使用
printf输出?为什么不std::cout? -
@Someprogrammerdude - 编译器可能不会将它们保留在发出的代码中。但它们确实会影响标准观点的表达式的语义。这根本不是 id 表达式(或名称)。
-
在您引用的部分之后不久,标准说:当尚未绑定到引用的临时类对象将被复制/移动到具有相同 cv-unqualified 的类对象时类型,可以通过将临时对象直接构造到省略的复制/移动的目标中来省略复制/移动操作这个规则,结合你引用的那个,允许
return *&f;的复制省略。跨度> -
@pschill:
fingetFoo不是临时对象。
标签: c++ language-lawyer