Reputation: 265
I have a problem where I want to store vectors of structs inside individual container class.
The problem is that while creating this container for these vectors, I waste resources because the vectors are copied; not moved. Why are the resources in the temporary returned by create()
not transferred to local variable master_data
in the main function?
Sample code that I assumed would work is presented below (and in 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;
}
Upvotes: 1
Views: 103
Reputation: 73366
Here:
Master(const Master &rhs) : data_a(std::move(rhs.data_a)), data_b(std::move(rhs.data_b)) {}
the parameters are constant, which prevent them from being moved, since they are immutable.
Try using something like this instead:
Master(Master&& rhs) : data_a(std::move(rhs.data_a)), data_b(std::move(rhs.data_b)) {}
where I dropped const
and enhanced your parameter with &&
.
Similarly for the constructor, you would do:
Master(std::vector<DataA>&& a, std::vector<DataB>&& b) : data_a(std::move(a)), data_b(std::move(b)) {}
Last, but not least, you should modify your create function like so (otherwise you will get a compilation error about not being able to bind):
Master create() {
...
return {std::move(data_a), std::move(data_b)};
}
Upvotes: 1
Reputation: 4473
Your constructor:
Master(const std::vector<DataA> &a, const std::vector<DataB> &b);
accepts the a
and the b
parameters as constant references. You have to define it to accept rvalue references as following:
Master(std::vector<DataA>&& a, std::vector<DataB>&& b);
But in this case you have to indicate that data_a
and data_b
inside the create()
function may be moved:
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) };
}
Upvotes: 0