返回类型是实例还是简单赋值

时间:2013-06-19 20:28:08

标签: c++ return return-value

我一直在考虑我的问题的答案,所以我不得不问,返回类型是实例还是简单赋值?

以下面的示例为例:

class Convert {

public:

    int getValue (std::string const& _text);

};


Convert convert;
int total(0);

total = convert.getValue("488");

THEREFOR;结果从getValue()成员函数返回时发生了什么,步骤是什么?是否创建了返回类型int的实例,而不是从临时int复制到total变量的值,或者是直接分配到total的返回值需要创建临时返回类型int

因为我的部分代码有void getValue (int& _result, std::string const& _text);但int getValue (std::string const& _text)更符合逻辑。

2 个答案:

答案 0 :(得分:2)

复制elision是一种允许的优化,几乎每个编译器都支持。

复制省略意味着在某些情况下,创建临时副本,然后将该临时副本复制到命名变量,然后销毁临时副本,可以导致变量直接构造。

与返回值优化和移动语义一起,这意味着返回可移动的复杂对象是有效的。对于类似int的类型,as-if规则也在运行:编译器可以执行任何行为 - 如果执行代码行或代码块,并且编译器了解复制/移动时会发生什么int周围(即基本上没有),所以他们可以跳过那些复制/移动。

为了确保正确地发生RVO和复制省略,您需要执行以下操作:

int function() {
  int retval = 8; // create the return value in one spot, this makes NRVO possible
  // code goes here
  return retval; // you can have more than one return statement in most compilers
}

int result = function(); // initialize the variable result by assigning the return value of the function to it.

如果您执行上述操作,大多数编译器将直接在retval变量存储中构造result对象,如果可以看到function的正文,则根本不会发生任何副本result(有些人可能会这样做,即使你看不到function mayhap的身体)

在C ++ 11中还有其他技巧。

int function() {
  return {7}; // guaranteed to directly construct the return value without a copy
}

int result = function(); // even if copy elision is not done, the temporary `int` is moved into `result`.

如果你阻止复制省略:

int function() {
  int foo = 7;
  int bar = 3;
  // code
  if (foo>bar)
    return foo;
  else
    return bar;
}

只要返回局部变量,就会发生隐式移动。您还可以明确std::move到返回值。

现在,对于像int一样简单和小的类型,所有这些优化都是毫无意义的。当你处理更大,更昂贵的对象,比如std::vector std::vector时,每个对象都有10 MB的数据,这些技术意味着返回的按值最终会像传递指针要小心填充。

答案 1 :(得分:0)

您的完整表达式total = convert.getValue("488");是一个赋值表达式。评估它会将权限值赋给变量total。右边的值是评估子表达式convert.getValue("488");的结果。此值是类型int的临时值(右值)。

我真的不认为有一种更好的方式可以说“评估右侧的结果的价值被分配到左侧”。

优化编译器可能很好地意识到该类是空的,total0的初始化是不可观察的,并且将所有内容都折叠成非常短的内容。