2009-05-23 65 views
10

这编译:STL容器分配和const指针

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! 

什么是嵌套的常量指针类型的等价规则?我认为转换是隐含的。此外,我宁愿不实施STL容器的按点分配,除非我真的必须。

回答

44

直接分配是不可能的。正如其他人所解释的,等价性不是由指针类型确定的,而是由容器类型确定的。在这种情况下,矢量不想接受有不同,但兼容的元素类型的另一种载体。

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

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

为什么?我会理解是犹豫是否将矢量隐式转换为矢量,但int *为const int *?我认为const在这方面受到特殊待遇。任何想法为什么C++标准反对它? – 2009-05-24 20:10:58

7

的问题是不是指针,但类型的两个向量。模板类型之间没有标准转换,例如v1和v2。

这也许是更容易在下面的代码看看:从int*const int*

#include <vector> 
using namespace std; 

int main() { 
    vector <char> cv; 
    vector <int> iv; 
    cv = iv; // error 
} 
20

转换是建立在语言,但这些载体具有从一个到另一个没有自动转换。

3

这将是完全可以编写自己的vector的版本,其中这是可能的。这将是等同于标准型,但有一个模板化版本的operator=,这样的事情:

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

其中T是全班的元素类型,而A是任何类型分配给T.

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

4

在C++模板类中,模板中的每个实例化是一个完全不同的类 - 有vector<int *>vector<const int *>之间尽可能多的差作为有vector<int *>vector<string>或任何其它两个类为此事之间。

这是可能的,该委员会可能添加了一个转换操作符上vectorvector<U>Earwicker建议 - 你可以继续提供这样的功能的自己的实现:

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,用它的举动构造,这将是非常糟糕的表现,明智的。

1

Coercion by Member Template成语是解决问题的一种可能的方法。本质上,一个构件模板拷贝赋值运算符被添加,其允许模板类参加同一隐式类型转换(强制),它们否则可能仅在类模板的类型的参数。虽然这个成语在其他地方的STL中使用,但它在std :: vector中不可用。

2

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

v2 = reinterpret_cast<std::vector<const int *> & >(v1);

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

2

任何以前的答案都没有提到的重要一点是模板专业化使得无法在全语言基础上实现这一点。考虑:

template<class T> 
class Test 
{ 
    T t; 
}; 

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

因此Test<const int>包含字符数组,而Test<int>包含 单个int。

#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<foo *>vector<const foo *>可以 都很难有所不同---特别是,它们可能具有相同的大小。然而,显式模板专业化的可能性意味着它们可能会有很大差异,因此编译器不愿意允许转换。

(这个答案大多是从http://bytes.com/topic/c/answers/449611-cast-vector-foo-vector-const-foo#post1717570复制)