I have made the following little Program: (basically a class that couts if it gets created, copied or destroyed and a main that does some of that)
class Foo
{
public:
Foo(string name): _name(name)
{
cout << "Instance " << _name << " of Foo created!" << std::endl;
};
Foo(const Foo& other): _name(other._name)
{
cout << "Instance " << _name << " of Foo copied!" << std::endl;
};
~Foo()
{
cout << "Instance " << _name << " of Foo destroyed!" << std::endl;
}
string _name;
};
int main( int argc, char**argv)
{
Foo albert("Albert");
Foo bert("Bert");
{
vector<Foo> v1, v2;
system("PAUSE");
v1.push_back(albert);
system("PAUSE");
v2.push_back(bert);
system("PAUSE");
v1 = v2;
system("PAUSE");
}
system("PAUSE");
}
The output looks like this:
Instance Albert of class Foo created!
Instance Bert of class Foo created!
Press any key...
Instance Albert of class Foo copied!
Instance Albert of class Foo copied! // why another copy?
Instance Albert of class Foo destroyed! // and destruction?
Press any key...
Instance Bert of class Foo copied!
Instance Bert of class Foo copied!
Instance Bert of class Foo destroyed!
Press any key... // v1=v2 why did the albert instance not get destroyed?
Press any key...
Instance Bert of class A destroyed!
Instance Bert of class A destroyed!
Press any key... // there's still an albert living in the void
This strikes me as very odd. Why do I even bother passing something as a reference if it gets copied twice anyway? Why does the v1.operator=(other) not destroy the elements it contains? It would fit nicely with the behaviour of shared_ptr. Can someone tell me why?
ADDITION I put this in an endless loop and checked the mem usage, it doesn't seem to produce a mem leak at least.
ADDITION Ok, the mem is not an issue because it uses operator= rather than the copy ctor, ok thanks. When I add
v1.reserve(10);
v2.reserve(10);
the logical number of copies takes place. without that it reallocates and copies the whole vector for every single push_back, (which I find quite retarded even for small vectors). Looking at this I will consider using .reserve more and optimize my assignment operators Like hell :)
ADDITION: SUMMARY
- All these issues seem specific to VC++2005.
- If the size of the two containers match, my implementation uses operator= on the elements instead of destroying the old ones and copying the new ones, which seems sound practice. IF the sizes differ, normal destruction and copying are used.
- With the 2005 Implementation, one has to use reserve! Otherwise abysmal and not std compliant performance.
- These black boxes are much blacker than I thought.