【问题标题】:Constness of STL containers and their elements - when to use const?STL 容器及其元素的常量 - 何时使用常量?
【发布时间】:2015-05-14 09:33:37
【问题描述】:

我对 STL 容器及其元素的 const-ness 进行了过度思考(有些人可能会说思考不足,让我们看看会发生什么)。

我一直在寻找对此的讨论,但结果却出人意料地稀少。所以我不一定要在这里寻找一个明确的答案,我会很高兴有一次讨论让我头脑中的齿轮再次运转起来。

假设我有一个将 std::strings 保存在 std::vector 中的类。我的课是从字典文件中读取单词的字典。他们永远不会改变。因此,将其声明为

似乎是谨慎的
std::vector<const std::string> m_myStrings;

但是,我已经阅读了分散的 cmets,您不应该在 std::vector 中使用 const 元素,因为这些元素需要是可分配的。

问题:

  • 是否存在在 std::vector 中使用 const 元素的情况(不包括 hack 等)?

  • 其他容器中是否使用了 const 元素?如果有,是哪些,什么时候?

我在这里主要将值类型作为元素而不是指针来讨论。

【问题讨论】:

    标签: c++ c++11 vector stl constants


    【解决方案1】:

    我的类是一个从字典文件中读取单词的字典。它们永远不会改变。

    封装可以在这里提供帮助。

    让您的班级保留vector&lt;string&gt;,但将其设为私有。 然后向您的类添加一个返回 const vector&lt;string&gt; &amp; 的访问器,并让调用者通过它。

    调用者无法更改向量,向量上的operator [] 会交给他们const string &amp;,这正是你想要的。

    【讨论】:

    • 这是一个很好的建议,这几乎就是我决定要做的。不过,由于您的解决方案需要制作整个向量的副本,我可能会提供一个类似于此的接口:void iterateWords(std::function&lt;void (const std::string&amp;)&gt; func);:然后调用者可以提供一个 lambda 函数来对字符串执行任何操作。
    【解决方案2】:

    ,因为你说的原因。

    【讨论】:

    • 好吧,一个简单的不就足够了——至少这意味着我理解正确。编辑:我真的希望编译器能够捕捉到这种用法。不过,我意识到它有理由不这样做。
    • @Leander:好的,一个简单的“好的”就足够了。
    【解决方案3】:

    std::vector 的上下文中,我认为使用带有模板参数的const 限定符没有意义,因为std::vector 本质上是动态的,可能需要“移动”在内存中以“调整”自身。

    在 C++03 标准中,std::vector 保证存储在连续内存中。这几乎需要使用某种形式的数组来实现std::vector。但是我们怎样才能创建一个动态大小变化的数组呢?我们不能简单地将内存“附加”到它的末尾——这要么需要一个额外的节点(和一个链表),要么实际上将我们的额外条目物理地放在数组的末尾,这要么超出-限制或要求我们首先保留更多内存。

    因此,我假设std::vector 需要分配一个额外的数组,将其成员复制或移动到结束数组,然后删除旧的。

    不保证std::vector 的每个可模板对象的移动或复制分配不会改变被移动或复制的底层对象——这被认为是一种好的形式添加 const 限定符,但这不是必需的。因此,我们不能允许std::vector&lt;const T&gt;

    相关:How is C++ std::vector implemented?

    【讨论】:

      【解决方案4】:

      考虑使用

      std::vector<std::shared_ptr<const std::string>> 
      

      改为?

      【讨论】:

      • 感谢您的建议,但我试图避免这里的指针,即使是聪明的指针。 :)
      • “我在这里主要将值类型作为元素来讨论,而不是指针。”
      • 无论如何,这并不能回答问题。
      猜你喜欢
      • 2013-07-02
      • 1970-01-01
      • 1970-01-01
      • 2011-07-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-21
      • 2015-06-15
      相关资源
      最近更新 更多