【问题标题】:Cast vector<T> to vector<const T>将 vector<T> 转换为 vector<const T>
【发布时间】:2010-05-19 18:54:58
【问题描述】:

我有一个vector&lt;T&gt; 类型的成员变量(其中 T 是一个自定义类,但它也可以是 int。) 我有一个函数,我想从中返回一个指向该向量的指针,但我不希望调用者能够更改向量或其项。所以我希望返回类型为const vector&lt;const T&gt;*

我尝试过的所有铸造方法都不起作用。编译器一直抱怨 T 与 const T 不兼容。

这里有一些代码展示了我正在尝试做的事情的要点;

vector<int> a;
const vector<const int>* b = (const vector<const int>* ) (&a);

此代码无法为我编译。

提前致谢!

【问题讨论】:

标签: c++ constants


【解决方案1】:

如果您有const vector&lt;int&gt;,则不能修改容器,也不能修改容器中的任何元素。你不需要const vector&lt;const int&gt; 来实现这些语义。

【讨论】:

  • 我应该在我问之前测试一下。我现在测试了它,它就像你描述的那样工作。谢谢。
  • 但是如果我有vector呢?大多数时候创建这样的向量是有意义的。
  • @user3111311 号
【解决方案2】:

除了 James 关于如何做的回答之外,您应该注意 const int 不是放入任何标准容器的有效类型,因为它不可分配。

【讨论】:

    【解决方案3】:

    关于为什么 vector&lt;T&gt; 不能正确转换为 vector&lt;const T&gt; 即使 T 可以转换为 const T

    这是编程中经常出现的常见问题,无论是常量还是继承(派生对象的容器不能转换为基础对象的容器,即使包含的元素本身可以)。问题是每个元素都可以转换,但容器本身不能不破坏类型系统。

    如果您被允许使用vector&lt; const T &gt; &amp;vr = my_vector_of_T,那么您将被允许通过vr 添加元素,并且这些元素根据定义将是常量。但与此同时,这些相同的元素将在 my_vector_of_T 中作为非常量元素的别名,并且可以通过该接口进行修改,从而破坏类型系统中的 const 性。

    vector&lt;int&gt; 转换为vector&lt;const int&gt; 的特殊情况下,您可能不会注意到真正奇怪的效果——除了向vector&lt;const int&gt; 添加一个元素并查看常量 元素随时间变化,但仍然记住,给定两个相关类型 T1T2 存在关系,在大多数情况下,尝试将相同的关系应用于 T1T2 的容器将会中断类型系统。

    【讨论】:

    • +1 用于解释为什么即使容器中的引用是 const 更改容器也会导致问题。
    【解决方案4】:

    你可以像这样强制转换:

    b = reinterpret_cast<const std::vector<const int>*>(&a);
    

    但我不认为你应该这样做,因为它不能保证工作,只能编译

    【讨论】:

    • 由于 OP 使用了 c 风格的演员表,这实际上是他们试图做的。当类型不相关且 vector 与 vector 或其他任何内容无关时,c 样式转换将执行重新解释转换。
    【解决方案5】:

    编译器决定阻止它。但是,我们知道这是安全的,所以也许我们可以愚弄它:

    const vector<const int>* b = (const vector<const int>* )(void *)(&a);
    

    【讨论】:

    • 嗯,这不安全。 std::vector&lt;const int&gt; 类型无效,因为 std::vector&lt;T&gt; 要求 T 是可分配的,而 const int 不是。
    • 有趣的是我使用了一个编译器,它会编译这个,直到你尝试写入向量然后你得到一个非常模糊的编译器错误。
    • “我们知道这是安全的”——哈哈,哇!对于reinterpret_cast,除了[un/signed] char const * 之外,“安全”从来都不是一个合适的说法。如果您 幸运 并且愿意编写易碎的不可移植代码,那么其他一切都是实现定义的。此外,(A)T const 不是有效的元素类型,并且(B)即使是,标准也不需要将 2 个实例化的成员变量以相同的顺序排列,所以即使 reinterpret_cast 确实重新解释了对象表示在你的编译器上,假设兼容的成员生活在两者中的等效偏移量是愚蠢的
    猜你喜欢
    • 2019-10-20
    • 2020-10-17
    • 1970-01-01
    • 1970-01-01
    • 2016-03-31
    • 2021-06-02
    • 2016-10-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多