为什么在C++中的容器中存储引用(而不是指针)不起作用?

Jul*_*ner 24 c++ containers stl reference

在我的程序中,我有一个STL集.

set<string> myStrings;
Run Code Online (Sandbox Code Playgroud)

为了提高代码的效率,我把它改为hold,只有指针.(我不需要存储实际的字符串副本.)

set<string*> myStrings;
Run Code Online (Sandbox Code Playgroud)

我已经读过,在可能的情况下用指针替换指针是一个好习惯.(当然,仅当不需要指针的实际功能时.)

set<string&> myStrings;
Run Code Online (Sandbox Code Playgroud)

但后者给了我很多编译器错误.为什么不能将引用用作容器元素?

Jam*_*lis 45

容器存储对象.引用不是对象.

C++ 11规范明确指出(§23.2.1[container.requirements.general]/1):

容器是存储其他对象的对象.

  • @mojuba - 在C++中,当我们说对象时,我们指的是任何数据类型的实例,包括builtins. (8认同)
  • @mojuba:`int`和`int*`都是对象(在C++中,"一个对象是一个存储区域."(C++ 03 1.8/1)).引用永远不是对象.引用C++标准,"容器是存储其他对象的对象"(23.1/1). (8认同)
  • 那不是一个好答案。C ++中的容器可以包含任何内容,而不仅仅是对象。例如,您可以设置set &lt;int&gt;,set &lt;int *&gt;等。引用是物理级别的指针,但是因为编译器需要实例化采用对您的元素类型的引用的函数,并且因为C ++无法处理双重引用,set &lt;int&&gt;是不可能的。 (3认同)
  • @mojuba - 编译器中出现的错误取决于编译器提供的容器的特定实现.该标准并未强制要求任何特定实施.该标准采用了非常黑盒子的方法.它说"容器的值类型必须是可复制构造和可分配的",而不必担心如何完成复制和分配. (3认同)
  • 当然在纸上STL是一个黑盒子,但我打赌所有C++编译器都会因为同样的原因而在set <string&>上失败.我们试图在这里回答一个相当简单的问题,不是吗?此外,参考文献是完全可构造和可分配的.它们唯一的问题是在refs的情况下构造和赋值具有不同的语义,并且在double refs的情况下这些操作是不明确的.就这样. (2认同)
  • @mojuba:不,那不是真的。编译将在特定 STL 实现尝试使用赋值操作的第一个位置失败。这可能是模板实现代码深处的 20 个函数调用,或者是 2 个函数调用深处,并且仍然很好地符合标准。哦,不,引用不可分配。 (2认同)
  • @James McNellis:我现在同意你对原始问题的回答是正式的,但我仍然认为这不是给那些(显然)没有C++经验的人的最佳答案. (2认同)

Tim*_*ine 14

与"为什么"没有直接关系,但为了回答这样做的隐含愿望,我想提一下c ++ 11标准库有一个引用包装类型来启用它.它可以隐式转换为引用,并且可以存储在标准容器中.


Lea*_*ner 6

由于容器存储对象,引用不是对象。如果您使用的是 c++ 11,则可以使用 std::reference_wrapper 将事物包装到可分配对象。

http://en.cppreference.com/w/cpp/utility/functional/reference_wrapper

std::reference_wrapper 是一个类模板,它将引用包装在可复制、可分配的对象中。它经常用作将引用存储在通常不能保存引用的标准容器(如 std::vector)中的机制。