将传递引用转换为传递返回

时间:2013-07-31 15:18:02

标签: c++ function c++11 refactoring pass-by-reference

我有以下功能:

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;
}

2 个答案:

答案 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的几个字段而不是其数据。这比复制其内容快得多。