我有以下功能:
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;
}
答案 0 :(得分:3)
明显的答案是正确的,基本上是最优的。
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
vector
包括复制~3个指针的值,然后将源归零,无论do_stuff_better()
有多大。不需要复制或移动任何元素。
我们删除了return
中的命名局部变量,我们移除了do_stuff_better()
的{{1}}值而不是直接构造bob
的上述两个省略,都是有点脆弱。学习允许编译器执行这些操作的规则,以及编译器实际执行这些操作的情况,是值得的。
作为一个如何脆弱的例子,如果你有一个分支,你在检查错误状态后在你的return std::vector<int>()
中执行了do_stuff_better()
,那么功能上的省略可能会被阻止。 / p>
即使elision被阻止或者你的编译器没有为一个案例实现它,容器是move
'd的事实意味着运行时成本将是最小的。
答案 1 :(得分:1)
我认为,您必须详细了解move semantics(链接到Google查询,有很多论文 - 只需选择一个)。
简而言之,在C ++中,所有STL容器都是以这种方式编写的,从函数返回它们将导致它们的内容从返回值(所谓的右侧引用)移动到您为其分配的变量。实际上,您只会复制std :: vector的几个字段而不是其数据。这比复制其内容快得多。