代码与报错
在我的映像里,C++11的emplace函数的主要作用是减少一次类的构造函数调用。即在insert函数中构造函数可能被调用两次(一次指定的构造函数和一次复制构造函数),在emplace函数中应当不会用到复制构造函数。但是今天遇到了一个问题,代码如下
#include <iostream>
#include <cstring>
#include <string>
#include <vector>
#include <fstream>
#include <map>
#include <cstdio>
using std::cout;
using std::endl;
using std::map;
using std::string;
using std::vector;
class Test
{
public:
Test()
{
printf("Default Constucter\n");
}
Test(const string &str)
{
printf("String Constructer %s\n", str.data());
}
private:
Test(const Test &t)
{
printf("Copy Constructer\n");
}
};
int main()
{
map<string, Test> m;
string name("123");
m.emplace(name, name);
return 0;
}
按照这种写法,直观地想不会调用复制构造函数,那么为了安全把复制构造函数写成private的应该不会出问题,结果出现了如下的报错:·
main.cpp:37:22: required from here
main.cpp:28:2: error: ‘Test::Test(const Test&)’ is private
Test(const Test &t)
^
In file included from /usr/include/c++/4.8.2/bits/stl_algobase.h:64:0,
from /usr/include/c++/4.8.2/bits/char_traits.h:39,
from /usr/include/c++/4.8.2/ios:40,
from /usr/include/c++/4.8.2/ostream:38,
from /usr/include/c++/4.8.2/iostream:39,
from main.cpp:1:
/usr/include/c++/4.8.2/bits/stl_pair.h:134:45: error: within this context
: first(std::forward<_U1>(__x)), second(__y) { }
^
make: *** [build/objs/main.o] Error 1
表示需要复制构造函数。然而把复制构造函数写到public中也没有发现复制构造函数会被调用。这就很神奇了……
解决方案
原因具体比较复杂,解决方案如下[1] [2]:
方法是使用piecewise_construct与tuple,即
m.emplace(std::piecewise_construct,
std::forward_as_tuple(name),
std::forward_as_tuple(name));
这种写法不会报错
参考资料
https://codeday.me/bug/20180612/177887.html
http://www.cplusplus.com/reference/utility/piecewise_construct/
错误原因会在今后添加