I want to avoid making copies of a vector that is quite large. Here is a pretty clear example of what the issue is:
struct MyStruct {
std::vector<int> v;
int x;
}
class MyClass {
MyStruct lastStruct_;
public:
MyStruct create_struct() {
MyStruct s = { std::vector<int>(1000000, 1), 1234 };
lastStruct_ = s; // THIS IS A FULL COPY, PROBLEM
return s; // THIS SHOULD NOT BE A COPY AS PER C++11 AND UP
}
MyStruct getLastStruct() {
return lastStruct_;
}
}
void main()
{
MyClass c;
for (int i = 0; i < A_LOT; i++)
{
writeToDisk(c.create_struct());
}
//MEANWHILE IN OTHER THREAD:
// while(true)
// updateUI(c.getLastStruct());
}
How can I avoid making copies here ? I am trying to solve this with shared pointers but I am still new to these. Would something like this work (syntax might be off)?
struct MyStruct {
std::vector<int> v;
int x;
}
class MyClass {
std::shared_ptr<MyStruct> lastStruct_;
public:
MyStruct create_struct() {
auto s = std::maked_shared<MyStruct>({ std::vector<int>(1000000, 1), 1234 });
lastStruct_ = s;
return *s;
}
std::shared_prt<MyStruct> getLastStruct() {
return lastStruct_;
}
}
void main()
{
MyClass c;
for (int i = 0; i < A_LOT; i++)
{
writeToDisk(c.create_struct());
}
//MEANWHILE IN OTHER THREAD:
// while(true)
// updateUI(c.getLastStruct()->data());
}
Here's the most obvious way:
struct MyStruct {
std::vector<int> v;
int x;
}
class MyClass {
std::shared_ptr<MyStruct> lastStruct_;
public:
std::shared_ptr<const MyStruct> create_struct() {
auto s = std::maked_shared<MyStruct>({ std::vector<int>(1000000, 1), 1234 });
// acquire lock
lastStruct_ = s;
// release lock
return s;
}
std::shared_ptr<const MyStruct> getLastStruct() {
// acquire lock
auto j = lastStruct_;
// release lock
return j;
}
}
void main()
{
MyClass c;
for (int i = 0; i < A_LOT; i++)
{
auto j = c.create_struct();
writeToDisk(*j);
}
//MEANWHILE IN OTHER THREAD:
// while(true)
// {
// auto j = c.getLastStruct();
// updateUI(j->data());
// }
}
Notice that we replace the object by replacing a shared pointer to the old object with a shared pointer to the new object. The code that's accessing the old object keeps it alive until it's done with it.
You need some kind of lock to protect lastStruct_
from being modified in one thread while it's accessed in another thread.