简体   繁体   English

常量正确性导致指针容器出现问题?

[英]Const correctness causing problems with containers for pointers?

Given this code (C++, Qt containers are used but I suppose the question is universal):鉴于此代码(使用 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);
}

I get a compile error (MSVC2010):我收到编译错误 (MSVC2010):

error C2664: 'QList::indexOf' : cannot convert parameter 1 from 'const Item *' to 'Item *const &'错误 C2664:“QList::indexOf”:无法将参数 1 从“const Item *”转换为“Item *const &”
with
[ [
T=Item * T=项目 *
] ]
Conversion loses qualifiers转换失去了限定符

I figurer that since indexOf() is declared with a const T & argument, the argument would become a const Item* & (reference to a pointer to an Item that's const) which is easily obtainable from a const Item* argument.我认为,由于indexOf()是使用const T &参数声明的,因此该参数将成为const Item* & (引用指向const Item* &的指针),这很容易从const Item*参数获得。 Unfortunately, since const T& t and T const &t are equivalent , for some reason the compiler seems to treat the argument as Item* const &t which reads as "reference to a const pointer to an item" which is a different thing and doesn't make the Item pointed to immutable.不幸的是,由于const T& tT const &t是等价的,出于某种原因,编译器似乎将参数视为Item* const &t ,它读作“对指向某个项目的 const 指针的引用”,这是另一回事,而不是使Item指向不可变。

Am I interpreting this correctly?我是否正确解释了这一点? Why does the compiler screw things up even though the function is declared in a way that says it won't alter the argument?为什么即使函数以一种不会改变参数的方式声明,编译器也会把事情搞砸? Is this really a case of how the const syntax equivalence can screw things up?这真的是 const 语法等价如何把事情搞砸的一个例子吗? Why does the compiler use the latter form over the former?为什么编译器使用后一种形式而不是前者? What can I do about it if I want to store pointers in containters and maintain strict const semantics?如果我想在容器中存储指针并保持严格的 const 语义,我该怎么办?

This is a case where you can use const_cast to remove the const -ness without violating the guarantee of your function.在这种情况下,您可以使用const_cast删除const -ness 而不会违反函数的保证。

// 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(const_cast<Item*>(item));
}

That's because indexOf is merely finding the pointer in the container, not dereferencing the pointer and mutating what's on the other side.那是因为indexOf只是在容器中找到指针,而不是取消引用指针并改变另一侧的内容。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM