本文介绍了括号中带有return语句的C ++ nrvo/copy省略的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在鬼混以下代码,并使用我的visual studio 2017应用程序和两个不同的在线编译器获得了不同的结果.在发布模式下,Visual Studio在两种情况下都不会执行复制/移动操作,而两个在线编译器只会在未加括号的return语句中执行复制/移动操作.我的问题是:谁是正确的,更重要的是底层规则是什么?(我知道您可以将括号与 decltype(auto)语法结合使用.但这不是当前用例.)

i was fooling around with the following code and got different results using my visual studio 2017 application and two different online compilers. in release mode visual studio does elide the copy/move in both cases, while the two online compilers just do it in case of the unparenthesized return statement. my question is: who is right and more importantly what are the underlaying rules. (i know you can use the parentheses in conjunction with the decltype(auto)syntax. but this is not the current usecase).

示例代码:

#include <iostream>
#include <cstdio>

struct Foo
{
    Foo() { std::cout << "default constructor" << std::endl; }
    Foo(const Foo& rhs) { std::cout << "copy constructor" << std::endl; }
    Foo(Foo&& rhs) { std::cout << "move constructor" << std::endl; }
    Foo& operator=(const Foo& rhs) { std::cout << "copy assignment" << std::endl; return *this; }
    Foo& operator=(Foo&& rhs) { std::cout << "move assignment" << std::endl; return *this; }
};

Foo foo_normal()
{
    Foo a{};
    return a;
}

Foo foo_parentheses()
{
    Foo a{};
    return (a);
}

int main()
{
    auto a = foo_normal();
    auto b = foo_parentheses();
    std::getchar();
}

在线编译器1: http://cpp.sh/75bux

在线编译器2: http://coliru.stacked-crooked.com/a/c266852b9e1712f3

Visual Studio在发布模式下的输出为:

the output for visual studio in release mode is:

default constructor
default constructor

在其他两个编译器中,输出为:

in the two other compilers the output is:

default constructor
default constructor
move constructor

推荐答案

GCC是正确的.

根据 [class.copy.elision]第1段:

    expression 非易失性自动对象的名称(除了由 handler ([except.handle])的 exception-declaration 引入的函数参数或变量之外)具有相同类型(忽略cv-qualification)作为函数返回类型,通过将自动对象直接构造到函数调用的返回对象中,可以省略复制/移动操作
  • in a return statement in a function with a class return type, when the expression is the name of a non-volatile automatic object (other than a function parameter or a variable introduced by the exception-declaration of a handler ([except.handle])) with the same type (ignoring cv-qualification) as the function return type, the copy/move operation can be omitted by constructing the automatic object directly into the function call's return object

...

return 语句中经过括号括的表达式不符合复制省略的条件.

Parenthesized expression in return statement does not meet the criteria for copy elision.

实际上,直到,在 return 语句中带括号的id表达式甚至不能被视为执行移动的右值.

In fact, until the resolution of CWG 1597, parenthesized id-expression in return statement cannot even be considered as an rvalue to perform a move.

这篇关于括号中带有return语句的C ++ nrvo/copy省略的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!