我一直在考虑我的问题的答案,所以我不得不问,返回类型是实例还是简单赋值?
以下面的示例为例:
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)
更符合逻辑。
答案 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
的临时值(右值)。
我真的不认为有一种更好的方式可以说“评估右侧的结果的价值被分配到左侧”。
优化编译器可能很好地意识到该类是空的,total
与0
的初始化是不可观察的,并且将所有内容都折叠成非常短的内容。