为什么函数返回不移动向量?

kee*_*r12 1 c++ c++17

在使用C#长时间工作之后,我正在使用C++ 17,并通过一些Project Euler问题来完成我的工作.无论如何,任何人都可以解释为什么createRandomVector(const int n)不"移动"创建的向量?我输出内存地址,它们只有在通过引用传递时才会保持不变(显然).以下是代码:

#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
#include <random>

using namespace std;

auto createRandomVector(const int n)
{
    vector<int> v(n);

    iota(begin(v), end(v), 1);
    shuffle(begin(v), end(v), std::mt19937());

    cout << &v << endl;
    return v;
}

void printVector(const vector<int>& v, ostream& os);

int main()
{
    auto v = createRandomVector(100);
    printVector(v, cout);

    cout << endl;

    cout << &v << endl;
    return 0;
}


void printVector(const vector<int>& v, ostream& os)
{
    cout << &v << endl;
    for_each(begin(v), end(v), [&os](auto& i)
    {
        os << i << " ";
    });
}
Run Code Online (Sandbox Code Playgroud)

这是输出:

00BBFC20
00BBFD38
100 73 64 ... 85 90
00BBFD38
Run Code Online (Sandbox Code Playgroud)

为什么第一个内存地址与第二个不匹配?我对移动在现代C++(static_cast)中是如何工作有一些了解.但为什么这不起作用?

M.M*_*M.M 5

这里有两个问题:移动和复制省略.

首先,移动:移动意味着有两个不同的对象,一个的内容被转移到另一个.(与被复制到另一个的内容相反).在C++中,对象的整个生命周期都有固定的地址.

示例代码段:

vector<int> a { 1, 2, 3, 4, 5 };
vector<int> b;
cout << &a << ", " << &a[0] << '\n';
b = std::move(a);
cout << &b << ", " << &b[0] << '\n';
Run Code Online (Sandbox Code Playgroud)

我没有运行这个,所以希望没有错字,但你应该看到,即使两个向量不同,int对象块也从一个转移到另一个.

如果添加到程序中,您的输出&v[0]应该会看到相同的效果.


其次,复制省略.C++标准使得可选的,在这种情况下,对于局部变量vcreateRandomVector实际中为预留的内存空间中创建vmain.在这种情况下,甚至不会有与该return步骤相关联的任何移动或复制操作.

这可能发生的条件是当函数按值返回时,return语句具有以下形式:return X;where X是没有装饰的局部变量的名称.

如果编译器确实采用此选项,那么程序的前两个输出将是相同的.显然,您的编译器只决定在发布模式下执行此操作.