利用 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);
接受 a
和 b
参数作为常量引用。您必须将其定义为接受右值引用,如下所示:
Master(std::vector<DataA>&& a, std::vector<DataB>&& b);
但在这种情况下,您必须指出 create()
函数中的 data_a
和 data_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) };
}
我有一个问题,我想在单个容器中存储结构向量 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);
接受 a
和 b
参数作为常量引用。您必须将其定义为接受右值引用,如下所示:
Master(std::vector<DataA>&& a, std::vector<DataB>&& b);
但在这种情况下,您必须指出 create()
函数中的 data_a
和 data_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) };
}