将传递引用转换为传递返回
Transforming pass-by reference into pass-by return
我有以下函数:
void read_int(std::vector<int> &myVector)
这使我可以通过它引用来填充myVector
。它是这样用的:
std::vector<int> myVector;
read_int(myVector);
我想重构一些代码(保留原始函数(以最终拥有以下内容:
auto myVector = read_int(); // auto is std::vector<int>
实现此目的的最佳中间函数是什么?
在我看来,以下直接的答案是次优的:
std::vector<int> read_int() {
std::vector<int> myVector_temp;
read_int(myVector_temp);
return myVector_temp;
}
显而易见的答案是正确的,而且基本上是最优的。
void do_stufF(std::vector<int>& on_this); // (1)
std::vector<int> do_stuff_better() { // (2)
std::vector<int> myVector_temp; // (3)
do_stuff(myVector_temp); // (4)
return myVector_temp; // (5)
}
在 (3( 处,我们在自动存储(在堆栈上(创建一个命名的返回值。
在 (5( 处,我们只从函数返回命名的返回值,并且除了函数中其他任何地方的命名返回值之外,我们永远不会返回任何其他内容。
由于 (3( 和 (5(,编译器被允许(并且很可能会(消除myVector_temp
对象的存在。 它将直接构造函数的返回值,并调用它myVector_temp
。 它仍然需要有一个现有的移动或复制构造函数,但它不会调用它。
另一方面,当调用do_stuff_better
时,一些编译器也可以在调用时省略赋值:
std::vector<int> bob = do_stuff_better(); // (6)
编译器被允许有效地传递一个"指向 bob 的指针",并告诉do_stuff_better()
在 bob
的位置构造它的返回值,也省略了这个副本构造(嗯,它可以安排调用的发生方式,使得do_stuff_better()
被要求构造其返回值的位置与bob
的位置相同(。
而在 C++11 中,即使两个省略号的要求都不满足,或者编译器选择不使用它们,在这两种情况下都必须执行move
而不是copy
。
在第 (5( 行,我们以简单明了的 return
语句返回一个本地声明的自动存储持续时间变量。 如果不省略,这使得返回成为隐式move
。
在第 (6( 行,该函数返回一个未命名的对象,这是一个右值。 当bob
从它构造时,它move
构造。
move
std::vector
包括复制 ~3 个指针的值,然后将源归零,而不管vector
有多大。 无需复制或移动任何元素。
上述两个省略,我们去掉do_stuff_better()
内的命名局部变量,去掉do_stuff_better()
的return
值,直接构造bob
,都有些脆弱。 学习允许编译器执行这些省略的规则,以及编译器实际执行省略的情况,是值得的。
作为它如何脆弱的示例,如果您有一个分支,在检查错误状态后在do_stuff_better()
中执行了return std::vector<int>()
,则函数中的省略可能会被阻止。
即使 elision 被阻止或编译器没有针对某个案例实现它,容器move
的事实也意味着运行时成本将降至最低。
,您必须阅读更多有关移动语义的信息(链接到Google查询,有很多关于此的论文 - 只需选择一个(。
简而言之,C++所有 STL 容器都是以这样的方式编写的,从函数返回它们将导致它们的内容从返回值(所谓的右侧引用(移动到您将其分配给的变量。实际上,您只会复制 std::vector 的几个字段,而不是其数据。这比复制其内容要快得多。
- 寿命延长从函数返回引用
- 了解C++如何返回引用并绑定到引用
- 返回引用实例和非引用实例(return mystr & vs mystr)之间的区别是什么?
- 从类返回引用向量
- 使用unique_ptr并返回引用,或者我应该使用shared_ptr并在需要时制作副本
- 混淆C++从函数返回引用
- 两个相同的重载运算符[]一个返回引用
- 为什么向量的.at()成员函数返回引用而不是迭代器
- C++使用和返回引用
- 返回 T 引用的 Const 函子禁止赋值
- 返回引用是否也会延长其生存期?
- 如何返回引用,然后递增迭代器
- 如果使用返回引用的函数初始化"auto"var,为什么它不声明引用类型?
- 我是否需要将 ref 与 make_pair 一起使用才能返回引用?
- 在 vector::at 返回引用后进行更改
- 为什么PyImport_ImportModule返回引用计数为 3 而不是 1 的 PyObject*
- 超出返回引用的单一实例生存期
- Boost.Python 返回引用现有 c++ 对象的 python 对象
- C++ 运算符 += 重载返回引用
- 如何声明接受转发引用并返回引用或副本的函数模板