2

我有以下功能:

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

2 回答 2

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必须使用 a 而不是 a copy

在第(5)行,我们以简单明了的return语句返回本地声明的自动存储持续时间变量。move如果没有省略,这使得返回是隐式的。

在第(6)行,函数返回一个未命名的对象,它是一个右值。当bob由它构造时,它- 构造move

moveing astd::vector包括复制〜3个指针的值,然后将源归零,无论它有多大vector。无需复制或移动任何元素。

上述两种省略,即我们在 中删除命名的局部变量do_stuff_better(),并删除 的returndo_stuff_better()并直接构造bob,都有些脆弱。学习允许编译器执行这些省略的规则以及编译器实际执行省略的情况是值得的。

作为一个脆弱的例子,如果你有一个分支,你在检查错误状态后做了一个return std::vector<int>()do_stuff_better()那么函数内省略可能会被阻止。

即使省略被阻止或者你的编译器没有为一个案例实现它,容器是move'd 的事实意味着运行时间成本将是最小的。

于 2013-07-31T19:40:22.047 回答
1

我认为,您必须阅读有关移动语义的更多信息(链接到 Google 查询,有很多关于此的论文 - 只需选择一个)。

简而言之,在 C++ 中,所有 STL 容器都是这样编写的,从函数中返回它们会导致它们的内容从返回值(所谓的右手引用)移动到您分配给它的变量。实际上,您只会复制 std::vector 的几个字段而不是其数据。这比复制其内容要快得多。

于 2013-07-31T15:41:48.033 回答