class A {
public:
explicit A(int x) {}
};
vector<A> v;
v.push_back(1); // compiler error since no implicit constructor
v.emplace_back(1); // calls explicit constructor
以上内容来自David Stone的video。我无法理解的是emplace_back
为什么要打电话
显式构造函数?我在C ++标准中没有看到任何内容
使这个合法化。只有在收听David Stone的youtube视频后,
我发现了这个。
现在,我尝试使用std::map
。
map<int, A> m;
m.insert(pair<int, A>(1, 2)); // compiler error since no implicit constructor
m.emplace(1, 2); // compiler error since no implicit constructor
为什么emplace
在这里失败?如果emplace_back
可以明确调用
构造函数,为什么emplace
没有做同样的事情?
答案 0 :(得分:3)
emplace
方法通过使用placement new operator
显式调用构造函数来插入元素。在安装到地图时,您需要单独转发构造键和值的参数。
m.emplace
(
::std::piecewise_construct // special to enable forwarding
, ::std::forward_as_tuple(1) // arguments for key constructor
, ::std::forward_as_tuple(2) // arguments for value constructor
);
答案 1 :(得分:2)
emplace
函数调用您的构造函数,如http://eel.is/c++draft/container.requirements.general#15.5标准中所述
T
EmplaceConstructible
从X
args
args
,对于零个或多个参数allocator_traits<A>::construct(m, p, args)
,意味着以下表达式格式正确:
std::allocator
这意味着它最终归结为你的分配器。查看该调用的参考意义,我们可以查看http://en.cppreference.com/w/cpp/memory/allocator_traits/construct
我们看到如果分配器没有构造成员函数,或者它是::new (static_cast<void*>(p)) T(std::forward<Args>(args)...)
,那么调用等同于
std::map<int, A>
对于T
,表达式中的std::pair<int const, A>
类型为args...
,1, 2
为emplace
。因此,要知道您对std::pair<int const, A>(1, 2)
的调用是否格式正确,我们只需要确定对std::pair
的调用是否有效。因此,我们会查看/*EXPLICIT*/ constexpr pair( const T1& x, const T2& y );
:http://en.cppreference.com/w/cpp/utility/pair/pair
有问题的构造函数列为int const &
(假设是C ++ 17)。换句话说,它就像调用一个接受A const &
作为第一个参数并且A
作为第二个参数的常规函数。 int
只能从emplace
明确构建,因此您的调用是不正确的。 explicit
调用仅在std::pair
上保存您正在构建的任何对象,在这种情况下只是{{1}},而不是该类型的任何参数。
答案 2 :(得分:1)
m.insert(std::pair<int, A>(1, 2))
编译,我不知道它为什么不为你编译。也许忘了-std=c++11
旗帜?这是因为std::pair
构造函数在将元素复制到first
和second
时显式调用构造函数。
如果您要加入std::map
,则必须在std::pair
中指定一个键和一个值。您可以使用std::make_pair
:
m.emplace(std::make_pair(1, 2));
这会编译,因为该对将在键/值对中构造到位,并且将调用显式构造函数。