是实例化返回类型还是简单地赋值
Are return types instanced or the value simply assigned
我一直在考虑我的问题的答案,所以我不得不问,是返回类型实例化还是值简单分配?
以以下示例为例:
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::vector
的std::vector
,每个对象都有10mb的数据,这些技术意味着按值返回最终和传递需要仔细填充的指针一样有效。
您的完整表达式total = convert.getValue("488");
是一个赋值表达式。对它求值,将右边的值赋给变量total
。右边的值是计算子表达式convert.getValue("488");
的结果。该值为int
类型的临时值(右值)。
我真的不认为有更好的方式来表达"右边求值的结果赋给左边"。
优化编译器可以很好地意识到类是空的,total
与0
的初始化是不可观察的,并将所有内容折叠成非常短的内容
- 为"adjacent"变量赋值时出现问题
- C++中的赋值发生,尽管右侧出现异常
- 用C++中的sscanf赋值
- 为std::string的某个索引赋值
- 重载Singly Linked List中的赋值运算符
- 为什么我必须在C++中添加一个赋值符号来声明一个数组
- gtest_使用setargpointee在函数中赋值
- 非常量变量只读位置的赋值
- 关于 c++ 函数中指针赋值的简单问题
- 奇怪的 G++ 错误,带有关于左值和赋值的简单代码
- 迭代器和简单的赋值/析构函数
- Boost 无锁队列断言用于简单的赋值和析构函数
- 简单的赋值会产生错误的值
- 简单的引用变量赋值导致对象的全局指针出现segfault
- 具有复制构造函数、简单赋值运算符和简单析构函数的动态大小的文本对象
- 'explicit' g ++ 中的关键字对简单构造函数(不是复制/赋值构造函数)没有影响?
- 是实例化返回类型还是简单地赋值
- 为什么c++编译器在这个简单的程序中没有给出优先级(赋值时的自增运算符)
- 为一个简单的派生类编写移动赋值运算符
- 在数组中赋值的简单方法