我注意到 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;