2017-08-08 51 views
14

看看这段代码:返回*&object时是否允许复制/移动elision?

#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),即允许复制/移动省音:在一个函数

return语句中有一类返回类型,当 表达式是具有相同cv-未定义 类型的非易失性自动对象(函数或catch-clause参数除外)的名称作为函数返回类型时,可以省略复制/移动操作 通过将自动对象直接构建到中函数的返回值

在我的示例中,返回表达式不是名称,所以我不认为允许使用elision。

我检查GCC /铛/ MSVC,虽然铛/ MSVC不复制的Elid,GCC一样。 GCC在这里违反标准吗?

+0

好吧,我不明白为什么编译器将保持冗余'* '和'&'操作符。另外,您使用的是哪个版本的编译器?你是用C++ 14模式构建的吗?另外,在引用标准时,请指明代码来自哪里(名称或章节/章节编号)。 –

+0

在完全不相关的说明中,为什么使用'printf'输出?为什么不'std :: cout'? –

+2

@Someprogrammerdude - 编译器可能不会将它们保留在发出的代码中。但是它们确实影响了标准观点表达式的语义。这根本不是一个id表达式(或名称)。 – StoryTeller

回答

0

首先,“为假设”规则在这里并不适用,因为你的复制和移动构造函数有副作用(他们执行IO)。因此,GCC不能在该标题下删除复制/移动。

快速浏览,我看不到任何其他的措辞将允许省音,所以我认为这是在GCC的错误。另一方面,我非常喜欢这个标准,以扩大复制/移动范围,以包含这个案例。 (在你提出的小例子,我看不出它是如何产生的问题 - 我相信你有一个大的例子,其中它。)

+0

即使在这种情况下有副作用,编译器也可以继续复制/移动。 – Zereges

+0

@Zereges当复制/移动elision被允许时,即使编译器有*副作用*(在标准中定义的形式意义上)也是允许的。我的第一段的要点是,如果施工人员没有副作用,那么即使在12.8/31(根据“如果”规则)下不允许使用“省略”,他们也可以被省略。 12.8/31不适用“在这种情况下”,“如果”不适用“在这种情况下”=> elision是一个错误。 –

+0

@Zereges我是否需要扩展我的答案以包含上述评论? –