如果将C ++ std :: map(和其他容器)与值类型一起使用,则会注意到插入到映射中会调用元素类型的析构函数。这是因为C ++规范要求操作符[]的实现等效于此:
(*((std::map<>::insert(std::make_pair(x, T()))).first)).second
它调用您类型的默认构造函数以构建该对。然后将该临时值复制到地图中,然后销毁。可以在此stackoverflow帖子中以及在codeguru上找到对此的确认。
我感到奇怪的是,这可以在不需要临时变量的情况下实现,并且仍然是等效的。C ++的一项功能称为“ inplace new”。std :: map和其他容器可以为对象分配空白空间,然后在分配的空间上显式调用元素的默认构造函数。
我的问题:为什么我见过的std :: map的实现都没有使用inplace new来优化此操作?在我看来,它将大大改善此低级别操作的性能。但是很多人已经研究了STL代码库,因此我认为一定有某种理由可以这样做。
通常,您可以指定一个较高级别的操作(例如[]
,较低级别的操作)。
在C ++ 11之前,[]
如果不使用,将很难做到insert
。
在C ++ 11中,添加std::map<?>::emplace
和类似的东西std::pair
使我们能够避免该问题。如果重新定义它,以便使用这种就地构造,则多余的(希望消除了)对象创建将消失。
我无法想到不这样做的原因。我鼓励您提出将其标准化的建议。
为了演示无复制插入std::map
,我们可以执行以下操作:
#include <map>
#include <iostream>
struct no_copy_type {
no_copy_type(no_copy_type const&)=delete;
no_copy_type(double) {}
~no_copy_type() { std::cout << "destroyed\n"; }
};
int main() {
std::map< int, no_copy_type > m;
m.emplace(
std::piecewise_construct,
std::forward_as_tuple(1),
std::forward_as_tuple(3.14)
);
std::cout << "destroy happens next:\n";
}
实时示例-如您所见,不会生成临时文件。
所以如果我们更换
(*((std::map<>::insert(std::make_pair(x, T()))).first)).second
与
(*
(
(
std::map<>::emplace(
std::piecewise_construct,
std::forward_as_tuple(std::forward<X>(x)),
std::forward_as_tuple()
)
).first
).second
不会创建任何临时文件(添加了空格,以便可以跟踪()
s)。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句