利用 C++ 中的移动语义

Taking advantage of move semantics in C++

我有一个问题,我想在单个容器中存储结构向量 class。

问题是,在为这些向量创建容器时,我浪费了资源,因为向量被复制了;没有动。为什么create()返回的temporary中的资源没有转移到main函数中的局部变量master_data

我认为可行的示例代码如下所示(在 coliru HERE 中):

#include <stdio.h>
#include <vector>
#include <stdlib.h>

// Specific data struct
typedef struct DataA {
    DataA(): a(rand()), 
             b(rand()) {}
    int a,b;    
} DataA;

// Another specific data struct
typedef struct DataB {
    DataB(): c(rand()), 
             d(rand()) {}
    int c,d;
} DataB;

// Container of all relevant data
typedef struct Master {
    Master(const std::vector<DataA> &a, const std::vector<DataB> &b) : data_a(std::move(a)), data_b(std::move(b)) {}
    Master(const Master &rhs) : data_a(std::move(rhs.data_a)), data_b(std::move(rhs.data_b)) {}

    std::vector<DataA> data_a;
    std::vector<DataB> data_b;
} Master;


Master create() {
    std::vector<DataA> data_a(10);
    std::vector<DataB> data_b(10);

    printf("data_a address inside create()   : %p\n", (void*)data_a.data());
    printf("data_b address inside create()   : %p\n", (void*)data_b.data());

    return {data_a, data_b};
}


int main()
{  
    Master master_data(create());

    printf("data_a address outside create()  : %p\n", (void*)master_data.data_a.data());
    printf("data_b address outside create()  : %p\n", (void*)master_data.data_b.data());
    return 0;
}

这里:

Master(const Master &rhs) : data_a(std::move(rhs.data_a)), data_b(std::move(rhs.data_b)) {}

参数是常量,这可以防止它们被移动,因为它们是不可变的。

尝试使用类似这样的东西:

Master(Master&& rhs) : data_a(std::move(rhs.data_a)), data_b(std::move(rhs.data_b)) {}

我删除了 const 并使用 && 增强了您的参数。

与构造函数类似,您可以这样做:

Master(std::vector<DataA>&& a, std::vector<DataB>&& b) : data_a(std::move(a)), data_b(std::move(b)) {}

最后但同样重要的是,你应该像这样修改你的创建函数(否则你会得到一个关于无法绑定的编译错误):

Master create() {
    ...
    return {std::move(data_a), std::move(data_b)};
}

你的构造函数:

Master(const std::vector<DataA> &a, const std::vector<DataB> &b);

接受 ab 参数作为常量引用。您必须将其定义为接受右值引用,如下所示:

Master(std::vector<DataA>&& a, std::vector<DataB>&& b);

但在这种情况下,您必须指出 create() 函数中的 data_adata_b 可能会被移动:

Master create() {
    std::vector<DataA> data_a(10);
    std::vector<DataB> data_b(10);

    printf("data_a address inside create()   : %p\n", (void*)data_a.data());
    printf("data_b address inside create()   : %p\n", (void*)data_b.data());

    return { std::move(data_a), std::move(data_b) };
}