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

Are return types instanced or the value simply assigned

本文关键字:赋值 简单 实例化 返回类型      更新时间:2023-10-16

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

以以下示例为例:

class Convert {
public:
    int getValue (std::string const& _text);
};

Convert convert;
int total(0);
total = convert.getValue("488");

样品;当结果从getValue()成员函数返回时发生了什么,步骤是什么?是创建了返回类型int的实例,然后将临时int的值复制到total变量中,还是直接将返回值赋给total而不需要创建临时返回类型int ?

因为我的一些代码有void getValue (int& _result, std::string const& _text);然而,int getValue (std::string const& _text)更符合逻辑。

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

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

结合返回值优化和移动语义,意味着返回可移动的复杂对象是高效的。对于像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.

如果你这样做,大多数编译器将直接在result变量存储中构造retval对象,如果function的体可以在result中看到,则根本不会发生复制(有些编译器可能即使看不到function的体也会这样做)

在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::vectorstd::vector,每个对象都有10mb的数据,这些技术意味着按值返回最终和传递需要仔细填充的指针一样有效。

您的完整表达式total = convert.getValue("488");是一个赋值表达式。对它求值,将右边的值赋给变量total。右边的值是计算子表达式convert.getValue("488");的结果。该值为int类型的临时值(右值)。

我真的不认为有更好的方式来表达"右边求值的结果赋给左边"。

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