【发布时间】:2013-10-09 21:17:18
【问题描述】:
我注意到 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 特有的,因为testing it in IDEOne(它使用 gcc 4.8.1)表明无关的移动总是在那里被省略。
这是怎么回事? 无法依赖被忽略的初始化副本让我很紧张。
注意:发布与调试版本的测试显示相同的结果。 (这是我所预料的,因为复制省略是独立于 MSVC 中的优化标志执行的。)
要测试的完整源代码(另请参阅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构造函数可能类似于pair( T&& = type1(), U&& = type2() )- 即,它可能在创建单个对时创建临时对象。但事实并非如此——有一个显式的平凡构造函数。下一个问题是,您是否在调试中这样做? -
@Yakk - 见我的笔记。调试与发布没有区别
-
呸,错过了。
auto重要吗? -
@Yakk - 我想我看到
auto没关系。一旦我用 VC11 回到机器上,我将不得不重新检查。 -
嗯...我用 VS2005 测试了这个(没有移动也没有自动),那里的副本也总是被忽略。
标签: c++ std-pair visual-c++-2012 copy-elision