Normally when I work with big objects, I like to use pointers just to ensure that I'm not copying data by accident (when I don't specify a copy constructor).
However, I also like to stay away from pointers to avoid memory corruption.
Today I'm using a library which returns objects directly. I'm wondering if it's safe for me to do the same without affecting performance:
1 2 3 4 5 6
BigClass someFunc()
{
BigClass bc();
bc.Load("GiantFile.csv");
return bc; //<-- Does this get optimized to avoid performance issues?
}
Also are you really sure that you are moving a giant object? Even if the giant file is really giant, are you really loading all that into the encapsulating object? Or does that object just hold a reference to it?
The about.com has three nice rules about references:
1. A reference must always refer to something. NULLs are not allowed.
2. A reference must be initialized when it is created. An unassigned reference can not exist.
3. Once initialized, it cannot be changed to another variable.
That was a really good article. But how can we be sure that our compiler implements Copy Elision? On occasion kicking up the optimizer has caused runtime problems for me when using rediculous amounts of polymorphism. In those cases, I take off the optimizer completely. Would I still get Copy Elision?
> how could the move constructor and move assignment operator.be implemented?
Trivially.
> but if you think copying primitives is inefficient you could always copy primitive pointers instead...
If you measure, and determine that copying these trivially copyable objects creates a performance bottleneck. And then determine that copying pointers actually improves performance.
On coliru, it does a million trivial copies of big in 0.03 seconds.
1 2 3 4 5 6 7 8 9 10
#include <cstdlib>
struct big{
int array [42];
};
big foo()
{
return big{ { std::rand() } } ;
}
#include <iostream>
#include <cstdlib>
struct big
{
int array [42];
};
big foo( const big& ) ;
int main()
{
std::srand(123456) ;
int x = 0 ;
big b ;
for( int i = 0 ; i < 1000*1000 ; ++i ) x += foo(b).array[0]%2 ;
std::cout << x << '\n' ; // statistically expected value: 500000
}
Phew, a whopping 0.035 seconds with copy + NRVO, instead of a mere 0.030 seconds with RVO alone.
For the same code, with a larger object (4KB, 24 times larger) and rep stosq enabled (alignment), the million copies takes 0.266 seconds (8 times longer).