I noticed something very strange with Visual Studio 2012: Defining a pair object like so:
auto objp = pair<int, LogMe>();
will not elide the copy/move of the pair in VC11, this call will print:
LogMe::LogMe - def.ctor!
LogMe::LogMe - move.ctor!
LogMe::~LogMe - dtor!
that is, a temporary pair will be created and then moved into the objp variable. (declaring it as pair<...> obj;
only logs the default ctor)
I have cross checked with my LogMe test object alone:
cout << "# Construct Object via auto obj = ...\n";
auto obj = LogMe();
# Construct Object via auto obj = ...
LogMe::LogMe - def.ctor!
and here the assignment will be elided.
This seems to be specific to VC11, as testing it in IDEOne (which uses gcc 4.8.1) shows that the extraneous move is elided always there.
What's going on here? Not being able to rely on the initialization copy being elided makes me nervous.
Note: Tests for release vs. debug version show the same result. (Which I would have expected, as copy-elision is performed independently of optimization flags in MSVC.)
Full sourcecode to test (See also the ideone link):
#include "stdafx.h"
#include <iostream>
#include <map>
using namespace std;
struct LogMe {
std::string member;
LogMe() {
cout << __FUNCTION__ << " - def.ctor!" << endl;
}
~LogMe() {
cout << __FUNCTION__ << " - dtor!" << endl;
}
LogMe(LogMe const&) {
cout << __FUNCTION__ << " - cpy.ctor!" << endl;
}
LogMe& operator=(LogMe const&) {
cout << __FUNCTION__ << " - cpy.assign.op!" << endl;
return *this;
}
LogMe(LogMe&&) {
cout << __FUNCTION__ << " - move.ctor!" << endl;
}
LogMe& operator=(LogMe&&) {
cout << __FUNCTION__ << " - move.assign.op!" << endl;
return *this;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
{
cout << "# Construct Object via auto obj = ...\n";
auto obj = LogMe();
cout << "# Construct pair<int, object> via auto objp = ...\n";
auto objp = pair<int, LogMe>();
cout << "# Construct pair<int, object> via pair objp2; ...\n";
pair<int, LogMe> p2;
}
return 0;
pair
constructor might be something likepair( T&& = type1(), U&& = type2() )
-- ie, it might be creating the temporary in creating the single pair. But that isn't the case -- there is an explicit trivial constructor. The next question would be, are you doing this in debug? – Assessorauto
matter? – Assessorauto
doesn't matter. I'll have to re-check once I get back to the machine with VC11. – Officinalmove
ctor confuses the vc11 elision optimizer? Should be checkable. – Assessor