use*_*508 23 c++ stl const vector
考虑一下
void f(vector<const T*>& p)
{
}
int main()
{
vector<T*> nonConstVec;
f(nonConstVec);
}
Run Code Online (Sandbox Code Playgroud)
下列情况不compile.The事情是vector<T*>不能转换到vector <const T*>,这不合逻辑对我来说,因为存在从隐式转换T*到const T*.为什么是这样 ?
vector<const T*>也不能转换为vector <T*>,但这是预期的,因为const T*无法隐式转换为T*.
MSa*_*ers 38
我在你的代码中添加了几行代码.这足以说清楚为什么不允许这样做:
void f(vector<const T*>& p)
{
static const T ct;
p.push_back(&ct); // adds a const T* to nonConstVec !
}
int main()
{
vector<T*> nonConstVec;
f(nonConstVec);
nonConstVec.back()->nonConstFunction();
}
Run Code Online (Sandbox Code Playgroud)
Nik*_*nić 22
vector<T>并且vector<const T>是不相关的类型.这个事实T可以被转换为const T在这里并不意味着一件事.
你必须从类型系统的角度考虑它.实例化vector<int>没有任何共同点vector<const int>.
Ste*_*sop 13
可能值得说明为什么执行所需的转换会违反const-correctness:
#include <vector>
const int a = 1;
void addConst(std::vector<const int *> &v) {
v.push_back(&a); // this is OK, adding a const int* to a vector of same
}
int main() {
std::vector<int *> w;
int b = 2;
w.push_back(&b); // this is OK, adding an int* to a vector of same
*(w.back()) = 3; // this is OK, assigning through an int*
addConst(w); // you want this to be OK, but it isn't...
*(w.back()) = 3; // ...because it would make this const-unsafe.
}
Run Code Online (Sandbox Code Playgroud)
问题是vector<int*>.push_back需要一个指向非const的指针(从现在开始我称之为"非const指针").这意味着,它可能会修改其参数的指针.特别是在vector的情况下,它可能会将指针移回给修改它的其他人.所以你不能将const指针传递给w的push_back函数,即使模板系统支持它,你想要的转换也是不安全的(它没有).const-safety的目的是阻止你将const指针传递给一个带有非const指针的函数,这就是它的工作方式.C++要求您具体说明是否要做一些不安全的事情,因此转换肯定不能隐含.事实上,由于模板的工作方式,根本不可能(见后文).
我认为C++原则上可以通过允许从一个转换保持常量安全vector<T*>&来const vector<const T*>&,就像int **到const int *const *是安全的.但这是因为定义了矢量的方式:对于其他模板来说,它不一定是安全的.
同样,它理论上可以允许显式转换.事实上,它确实允许显式转换,但仅适用于对象,而不是引用;-)
std::vector<const int*> x(w.begin(), w.end()); // conversion
Run Code Online (Sandbox Code Playgroud)
它不能用于引用的原因是因为模板系统不能支持它.如果允许转换,将会破坏的另一个示例:
template<typename T>
struct Foo {
void Bar(T &);
};
template<>
struct Foo<const int *> {
void Baz(int *);
};
Run Code Online (Sandbox Code Playgroud)
现在,Foo<int*>没有Baz功能.如何将指针或引用Foo<int*>转换为指针或引用Foo<const int*>?
Foo<int *> f;
Foo<const int *> &g = f; // Not allowed, but suppose it was
int a;
g.Baz(&a); // Um. What happens? Calls Baz on the object f?
Run Code Online (Sandbox Code Playgroud)
想象这样:
你有两个这样的课:
class V { T* t;};
class VC { T const* t;};
Run Code Online (Sandbox Code Playgroud)
你期望这两个类可以自动转换吗?
这基本上就是模板类.每种变体都是一种全新的变体.
因此,vector <T*>和vector <T const*>是完全不同的类型.
我的第一个问题是你真的想存储指针吗?
如果是的话,我建议看一下boost :: ptr_container.它保存指针并在向量被销毁时删除它们.但更重要的是,它将包含的指针视为普通的std:vector处理其包含的对象.因此,通过制作向量const,您只能以const形式访问其成员
void function(boost::ptr_vector<T> const& x)
{
x.push_back(new T); // Fail x is const.
x[4].plop(); // Will only work if plop() is a const member method.
}
Run Code Online (Sandbox Code Playgroud)
如果您不需要存储指针,则将对象(而不是指针)存储在容器中.
void function(std::vector<T> const& x)
{
x.push_back(T()); // Fail x is const.
x[4].plop(); // Will only work if plop() is a const member method.
}
Run Code Online (Sandbox Code Playgroud)