【发布时间】:2014-08-30 13:46:27
【问题描述】:
在尝试使用 C++11 智能指针和容器类时,我编写了两段代码,基本上可以归结为以下内容:
class Foo { ... };
typedef std::unique_ptr<Foo> FooPtr;
// First attempt; this did _not_ compile
typedef std::unordered_map<int, FooPtr> IntToFooMap;
// Second attempt; this _did_ compile
typedef std::unordered_map<int, const FooPtr &> IntToFooMap;
// here is the declaration causing the error in the second case:
IntToFooMap m {
{ 41, FooPtr(new Foo()) }
};
如您所见,首先我尝试定义一个未编译的FooPtr 的无序映射,因为FooPtr 是一个不可复制的std::unique_ptr(它有一个已删除的复制构造函数)。
更准确地说,是使用初始化列表初始化地图导致错误。
然而,令我大吃一惊的是,第二个版本,我将无序映射的value_type 定义为FooPtr 的const 引用,确实编译了。
直到今天,我认为一般情况下不可能将引用类型的值存储在标准容器中。虽然这种行为在某种程度上是可以直观理解的,但由于声明 (const) 引用可以防止 - 否则禁止 - 复制 unique_ptr,我仍然不完全理解它是如何工作或为什么工作的。 如果它确实有效,当然可以;如果这只是导致未定义行为的微妙极端情况,我不会感到惊讶。
【问题讨论】:
-
请注意,不可复制构造并不一定意味着不能将类型存储在容器中。现在 C++11 具有移动语义,标准容器可以存储可移动但不可复制的类型。
-
typedef std::unordered_map<int, FooPtr> IntToFooMap;在 g++ 4.8.2 上编译良好span> -
@Slava 作为记录,我使用的是 clang 3.4。
-
@user3477950 您的第二种情况导致引用悬空。 Note how 在这种情况下,
Foo在控制到达下一条语句之前被销毁。
标签: c++ c++11 reference copy-constructor