为什么C ++ std :: map :: operator []不使用inplace new?

srm

如果将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代码库,因此我认为一定有某种理由可以这样做。

Yakk-亚当·内夫罗蒙特

通常,您可以指定一个较高级别的操作(例如[],较低级别的操作)。

在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] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

为什么std :: sort不使用我的operator <实现

为什么不能为std :: unordered_map <std :: pair <int,int>,int>使用operator [],但不能为`std :: map`的相同键值对使用operator []?

为什么C ++ Map的operator <无法与<=一起使用

std :: map :: operator []

为什么std :: map重载运算符<不使用Compare

为什么在临时std :: ofstream对象上使用`operator <<`?

为什么使用{}来访问std :: hash中的operator()?

Netbeans在使用c ++ std :: map :: operator []时遇到了一些麻烦

std :: unordered_map :: operator []-为什么有两个签名?

为什么 std::map::operator[] 赋值需要无参数构造函数?

使用at()访问std :: map元素比使用operator []慢吗?

std :: map :: operator []表现异常

为什么在使用operator()对std :: set进行排序时必须实现operator <

C ++在std :: map <>中使用std :: set <>

为什么使用std :: map的代码无法编译?

当:: operator new足够时,为什么:: operator new []是必需的?

为什么选择std :: bitset :: reference :: operator〜?

std :: unordered_map :: insert与std :: unordered_map :: operator []

std :: map :: operator []比std :: map :: insert更有效?

应用`operator new(std :: size_t);`和`new-expression`有什么区别?

为什么无法根据其值字段直接使用std :: sort对std :: map进行排序

为什么std :: vector使用std :: allocator而不是new和delete运算符?

为什么 std::set 可以与我的自由函数 operator< 一起使用,而不是我的类成员函数 operator<?

为什么在使用std :: string :: operator []时自动变量不会成为引用?

为什么在使用`std :: find`时错误显示'operator =='不匹配?

为什么我不能使用 std::map[ ] 添加字符串,但 std::map.at() 有效?

在C ++中使用std :: allocator而不是new有什么优势?

为什么fstream不使用operator >>的istream原型?

为什么在执行operator <<时编译器为什么不能使用类的std :: string转换函数?