Reputation: 50278
#include <vector>
typedef std::vector<char> vc;
typedef std::vector<vc> vvc;
vvc f() {
const int N = (1 << 15);
return vvc(N, vc(N)); // 1 GB
}
int main () {
vvc v;
v = f();
while(true); // Why 2GB allocated ?
return 0;
}
Compiled with both clang -O2 and g++ -O2. Same behavior.
Edit: There are multiple ways to fix this code pointed in some of the answers. But my point is to understand this code. Of course there is a temporary object, but it should disappear at the semicolon and 1GB of memory should be returned to the system. The question intends to ask why it does not happen.
Edit 2: The destructor of temporary object is indeed called before semicolon.
Upvotes: 9
Views: 431
Reputation: 17163
You have assignment in your code that we preach against in vain for good reason ;-)
If you used initialization, that allows RVO optimization, and as others experimented it actually seem working too.
With assignment the function return an object, then it must be copied to target and only then nuke the temporary. While with data flow anal it could be possibly optimized, it's a case that hard to catch and considered rare to use. Thus you suffer the performance penalty on top of all the rest.
EDIT: to see that the temporary is indeed nuked at the proper point I suggest using debugger and single-step into functions. Alternatively look at assy listing. For the abstract machine the dtor call must happen before the next instruction.
However, optimized code uses the 'as if' rule more liberally. If the code has no way to tell the difference, it may postpone it a little, and you may just experience that effect.
C++11 note: in C++11 vector gained another op= that moves from the rvalue. That would cure this particular case, but it will take time till all compilers close the gap and especially all classes gain moving stuff. Pre-11 code looking for moving would use swap() in place of =.
Upvotes: 4
Reputation:
Edit: There are multiple ways to fix this code pointed in some of the answers. But my point is to understand this code. Of course there is a temporary object, but it should disappear at the semicolon and 1GB of memory should be returned to the system. The question intends to ask why it does not happen.
On Windows I compiled your test with gcc and ran. And I see that the value of Private Bytes
is increasing after start of the program and then starts decreasing and then finally stops changing. So on this OS memory is returned to the system. By the way I made use of Process Explorer
to get information about Private Bytes
.
I assume you did your test on Linux and on this OS memory is not returned to the system. If it is not used it is finally moved to a paging area if I am right.
Upvotes: 1
Reputation: 19721
My guess is that you're looking at the operating system display of how much memory is allocated to the process, and that your compiler doesn't yet support C++11's move assignment.
Therefore what happens is probably the following:
So the result is that the operating system allocates 2GB to your process, of which 1GB is allocated to the vector, and 1GB is free for future allocation within your program (but not to allocations in another process).
Upvotes: 4
Reputation: 622
I've just tested on win32, vc7.
Your code allocates 2Gb. If change to this:
int main () {
vvc v = f();
while(true);
It needs only 1Gb.
I suppose the reason - is a copy operation between vectors.
v = f()
- invokes constructor. Your case - default c'tor and copy (operator =
) into empty object. Coping needs 2 Gb.
Internal actions of f()
(creating vector and return) can use RVO, and there are no any coping and extra allocating.
Upvotes: 2
Reputation: 9608
I think the return value will be copied. Than temporary 2 copies of vvc exists. Each with 2^30 chars (= 1GB)
To my knowledge the compiler is allowed but not required to remove the copy operation
I found this link http://en.wikipedia.org/wiki/Return_value_optimization
Upvotes: 0