Я заметил кое-что очень странное в Visual Studio 2012: определение объекта пары следующим образом:
auto objp = pair<int, LogMe>();
не будет игнорировать копирование/перемещение пары в VC11, этот вызов напечатает:
LogMe::LogMe - def.ctor!
LogMe::LogMe - move.ctor!
LogMe::~LogMe - dtor!
то есть будет создана временная пара будет, а затем перемещена в переменную objp. (объявление его как pair<...> obj;
регистрирует только ctor по умолчанию)
Я проверил перекрестную проверку только с моим тестовым объектом LogMe:
cout << "# Construct Object via auto obj = ...\n";
auto obj = LogMe();
# Construct Object via auto obj = ...
LogMe::LogMe - def.ctor!
и здесь назначение будет исключено.
Похоже, это характерно для VC11, так как тестирование в IDEOne (использующем gcc 4.8.1) показывает, что посторонние ход опущен всегда.
Что здесь происходит? Невозможность полагаться на пропущенную копию инициализации заставляет меня нервничать.
Примечание. Тесты для выпуска и отладочной версии показывают одинаковый результат. (Чего я и ожидал, поскольку копирование-исключение выполняется независимо от флагов оптимизации в MSVC.)
Полный исходный код для тестирования (см. также ссылку на ideone):
#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
может быть чем-то вродеpair( T&& = type1(), U&& = type2() )
, т. е. он может создавать временные объекты при создании одной пары. Но это не так — есть явный тривиальный конструктор. Следующий вопрос: вы делаете это в режиме отладки? - person Yakk - Adam Nevraumont   schedule 10.10.2013auto
? - person Yakk - Adam Nevraumont   schedule 10.10.2013auto
не имеет значения. Мне придется перепроверить, как только я вернусь к машине с VC11. - person Martin Ba   schedule 10.10.2013move
ctor путает оптимизатор vc11 elision? Должен быть проверяемым. - person Yakk - Adam Nevraumont   schedule 10.10.2013