【问题标题】:STL container assignment and const pointersSTL 容器分配和 const 指针
【发布时间】:2009-05-23 22:51:16
【问题描述】:

这样编译:

int* p1;
const int* p2;
p2 = p1;

这不是:

vector<int*> v1;
vector<const int*> v2;
v2 = v1;  // Error!
v2 = static_cast<vector<const int*> >(v1);  // Error!

嵌套 const 指针的类型等价规则是什么?我认为转换是隐式的。此外,我宁愿不实现 STL 容器的逐点分配,除非我真的必须这样做。

【问题讨论】:

    标签: c++ gcc stl constants


    【解决方案1】:

    无法直接分配。正如其他人所解释的,等价不是由指针类型建立的,而是由容器类型建立的。在这种情况下,vector 不想接受另一个具有不同但兼容元素类型的向量。

    没有真正的问题,因为您可以使用assign 成员函数:

    v2.assign(v1.begin(), v1.end());
    

    【讨论】:

    • 为什么?我会理解对于将vector 隐式转换为vector,但将int* 转换为const int* 犹豫不决?我认为 const 在这方面受到特殊对待。知道为什么 C++ 标准决定反对它吗?
    • 也许与模板有关的东西完全匹配,并不总是最方便的。
    • 我在某处看到过这个例子:苹果是水果,但一袋苹果不是一袋水果。这将违反 Liskov 可替代性原则:您可以将橙子放入一袋水果中,但不能将橙子放入一袋苹果中。如果 Bag(或者,在你的情况下,vector)是不可变的,你就不会有这个问题。
    【解决方案2】:

    语言中内置了从int*const int* 的转换,但是这些向量不会自动从一种转换到另一种。

    【讨论】:

      【解决方案3】:

      问题不在于指针,而在于两个向量的类型。在您的示例中,模板类型之间没有像 v1 和 v2 这样的标准转换。

      这在下面的代码中可能更容易看到:

      #include <vector>
      using namespace std;
      
      int main() {
          vector <char> cv;
          vector <int> iv;
          cv = iv;    // error
      }
      

      【讨论】:

        【解决方案4】:

        在 C++ 模板类中,模板的每个实例化都是一个完全不同的类 - vector&lt;int *&gt;vector&lt;const int *&gt; 之间的差异与 vector&lt;int *&gt;vector&lt;string&gt; 或任何其他两个类之间的差异一样大事情。

        委员会可能会按照Earwicker 的建议在vectorvector&lt;U&gt; 上添加一个转换运算符 - 您可以继续提供您自己的此类函数的实现:

        template <class A, class T>
        vector<T> convert_vector(const vector<A> &other)
        {
            vector<T> newVector;
            newVector.assign(other.begin(), other.end());
            return newVector;
        }
        

        并像这样使用它:

        vector<int*> v1;
        vector<const int*> v2;
        v2 = convert_vector<const int*>(v1);
        

        不幸的是,在 C++0x 附带它的移动构造函数之前,这将是非常糟糕的性能。

        【讨论】:

          【解决方案5】:

          在可能的情况下编写自己的vector 版本是完全可能的。它将与标准类型相同,但具有operator= 的模板版本,如下所示:

          template <class A>
          vector2<T> &operator=(const vector2<A> &other)
          {
              assign(other.begin(), other.end());
              return *this;
          }
          

          其中 T 是整个类的元素类型,而 A 是可分配给 T 的任何类型。

          我不清楚为什么std::vector 没有这个。

          【讨论】:

            【解决方案6】:

            危险,除非你知道这些类型是绝对兼容的:

            v2 = reinterpret_cast&lt;std::vector&lt;const int *&gt; &amp; &gt;(v1);

            大多数 STL 实现都使用特殊化,所有指针向量共享相同的底层实现。这是因为 (void *) 通常与 (int *) 或任何其他指针类型的大小相同。

            【讨论】:

              【解决方案7】:

              前面的任何答案中都没有提到的一个重要点是模板专业化使得这不可能在语言范围的基础上实现。考虑:

              template<class T>
              class Test
              {
                  T t;
              };
              
              template<>
              class Test<const int>
              {
                  char array[1000];
              };
              

              因此Test&lt;const int&gt; 包含一个字符数组,而Test&lt;int&gt; 包含 一个整数。

              #include <iostream>
              using namespace std;
              
              int main()
              {
                  Test<int> t1;
                  Test<const int> t2;
                  cout << sizeof(t1) << endl; // gives 4
                  cout << sizeof(t2) << endl; // gives 1000
                  return 0;
              }
              

              实际上vector&lt;foo *&gt;vector&lt;const foo *&gt; 可能几乎没有区别 all --- 特别是,它们可能具有相同的大小。然而,可能性 显式模板专业化意味着它们可能不同 壮观,因此编译器不愿意允许转换。

              (这个答案大部分抄自http://bytes.com/topic/c/answers/449611-cast-vector-foo-vector-const-foo#post1717570

              【讨论】:

                【解决方案8】:

                Coercion by Member Template idiom 是解决问题的一种可能方法。本质上,添加了一个成员模板复制分配运算符,它允许模板类参与相同的隐式类型转换(强制),否则只能在类模板的类型参数上进行。尽管该成语在其他地方的 STL 中使用,但在 std::vector 中不可用。

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 2012-01-28
                  • 2011-04-13
                  • 2011-01-10
                  • 1970-01-01
                  • 2011-03-19
                  • 2014-08-23
                  • 1970-01-01
                  相关资源
                  最近更新 更多