利用C ++中的移动语义

时间:2017-07-09 11:08:30

标签: c++ class oop vector move-semantics

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

问题是在为这些向量创建这个容器时,我浪费了资源,因为向量被复制了;没动。为什么create()返回的临时资源未在主函数中传递给局部变量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;
}

2 个答案:

答案 0 :(得分:1)

下面:

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

答案 1 :(得分:0)

你的构造函数:

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

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

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

但在这种情况下,您必须指出data_a功能中的data_bcreate()可能会被移动:

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