【发布时间】:2014-01-03 03:24:36
【问题描述】:
鉴于此代码(使用 C++、Qt 容器,但我想问题是普遍的):
// a containter for Item-s
QList<Item*> items;
// argument is const to prevent changing the item by this function
void doStuff(const Item *item)
{
// find index of the item inside the container
// indexOf() is declared as:
// template <typename T> int QList<T>::indexOf(const T &t, int from = 0) const
const int itemIndex = items->indexOf(item);
}
我得到一个编译错误(MSVC2010):
错误 C2664:“QList::indexOf”:无法将参数 1 从“const Item *”转换为“Item *const &”
与
[
T=项目 *
]
转换失去限定符
我认为由于indexOf() 是使用const T & 参数声明的,因此该参数将成为const Item* &(对指向常量项的指针的引用),这很容易从const Item* 参数中获得。不幸的是,由于const T& t and T const &t are equivalent,由于某种原因,编译器似乎将参数视为Item* const &t,它读作“对一个项目的const指针的引用”,这是另一回事,不会使Item指向不可变的。
我的解释正确吗?为什么即使函数以一种不会改变参数的方式声明,编译器也会把事情搞砸?这真的是 const 语法等价如何搞砸事情的一个例子吗?为什么编译器使用后一种形式而不是前一种形式?如果我想在容器中存储指针并保持严格的 const 语义,我该怎么办?
【问题讨论】:
-
试试
items->indexOf(*item); -
@MadPhysicist: 不行,那个参数是
const Item类型,也不能转换成Item *const &。 -
好吧,您的 QList 是
Item*的列表,而不是const Item*的列表。你能逃脱QList<const Item*>吗?请记住T*、const T*、T* const和const T* const都是非常不同的东西 -
我认为这是指针语义与泛型编程相结合的产物。
const Item*(也写成Item const*)和Item* const是两种不同的类型;Item const*无法转换为Item* const。它也是泛型编程的产物,因为您可以将Item* const与Item const*进行比较,但QList的接口似乎不支持这一点(C++1y 将提供支持使用通用比较器 à lastd::less<>用于标准库容器)。 -
@neuviemeporte 事实上,
std::find(items.constBegin(), items.constEnd(), item)应该可以解决问题,因为它不假定T的类型与取消引用的迭代器的类型相同。标准库容器目前在指针的 const 正确性方面存在“同样的问题”,尽管它们没有那么多可能有问题的 member 函数。
标签: c++ pointers const-correctness container-data-type