【问题标题】:Construct-in-place an unmoveable object in a map在地图中就地构建不可移动的对象
【发布时间】:2019-11-02 13:06:22
【问题描述】:

我正在尝试在包含原子的地图中构造一个对象,因此它既不能被复制也不能移动 AFAICT。

我对 C++ reference 的解读是 map emplace 应该能够做到这一点。但是由于已删除或不存在构造函数,以下代码无法编译。使用make_pair 没有帮助。

#include <atomic>
#include <unordered_map>

class Z {
  std::atomic<int> i;
};

std::unordered_map<int, Z> map;

void test(void) {
  map.emplace(0, Z()); // error
  map[0] = Z(); // error
}

这可能吗?如果不可能,为什么不呢?

编辑:编译器是 gcc 4.8.1,在 Linux 上

【问题讨论】:

  • 你用什么编译器?
  • emplace 接受构造函数参数,但您传递的是一个临时对象。
  • @NeilKirk 那么如何调用无参数构造函数呢?
  • map[0]; 似乎有效。
  • std::unordered_map&lt;int, std::shared_ptr&lt;Z&gt;&gt; map; 怎么样?

标签: c++ c++11 move-semantics stdatomic


【解决方案1】:

map.emplace(std::piecewise_construct, std::make_tuple(0), std::make_tuple()) 将在位置 0 处构造一个零参数 Z

map[0] 如果还没有,也会这样做。

emplace 接受参数来构造std::pair&lt;const K, V&gt;std::pair 有一个带有 std::piecewise_construct_t 标记的构造函数,它接受两个元组,第一个用于构造第一个参数,第二个用于构造第二个参数。

所以std::pair&lt;const int, Z&gt; test( std::piecewise_construct, std::make_tuple(0), std::make_tuple() ) 就地构造tests 元素,const int 是用(0) 构造的。 Z 是用 () 构造的。

map.emplace forwards 是 std::pair 构造函数的参数。

【讨论】:

    【解决方案2】:

    最简单的解决方案是使用operator[] 在地图内部构造值。然后你可以分配一个值(或根据需要对其进行操作)。

    【讨论】:

      【解决方案3】:

      可能以下解决方案会更好,因为 atomic 不可复制:

      class Z {
        std::atomic<int> i;
      };
      
      std::unordered_map<int, std::shared_ptr<Z>> map;
      
      void test(void) {
        map.emplace(0, std::make_shared<Z>()); // OK
      }
      

      【讨论】:

      • shared_ptr 的开销不小。
      猜你喜欢
      • 1970-01-01
      • 2016-02-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-21
      • 2018-03-10
      • 2020-09-21
      相关资源
      最近更新 更多