6

AQList<T *>不容易是 const 正确的。考虑函数

void f(QList<T *> list)
{
    list[0]->constFunction();
}

我可以将 f 更改为

void f(QList<const T *> list)

但是我不能做

f(QList<T *>());    //Compile error

不再,因为编译器不能隐式QList<T *>转换为QList<const T *>. 但是,我可以明确地重新解释 QList,如下所示:

template <typename T> inline QList<const T *> &constList(const QList<T *> &list)
{
    return (QList<const T *> &)list;
}

这使我能够使用constList模板函数将 anyQList<T *>转换为 a QList<const T *>,如

f(constList(QList<T *>()));

它似乎工作正常,但这样做真的安全吗?

4

2 回答 2

8

您正在考虑的铸造功能,...

template< class T >
inline QList<T const*>& constList( QList<T*> const& list )
{
    return reinterpret_cast< QList<T const*>& >(
        const_cast< QList<T*>& >( list )
        );
}

... 可能是实用的(可能QList不会根据const元素类型的 -ness 改变其对象表示),但它可能会破坏const正确性

首先,因为抛弃const列表本身的 -ness 是不const正确的:它允许您更改原始const列表。

但即使那个正式的论点const被删除,比如......

template< class T >
inline QList<T const*>& constList( QList<T*>& list )
{
    return reinterpret_cast< QList<T const*>& >(
        list
        );
}

…仍然存在const正确性问题。

原因是列表构成了额外的间接级别,并且您的函数不是本身const。因此,在使用您的函数获取对带有指向const元素的指针的列表的引用之后,您可以在该列表中存储一个指向真正的东西的指针const。然后你可以使用原始列表来修改那个真正的const项目bang

这与没有从to的隐式转换T**T const**的原因相同。

如果没有这些问题,您可以做的是,使用已经const指向对象的指针列表,使那些指向对象的指针const

template< class T >
inline QList<T const*> const& constList( QList<T*> const& list )
{
    return reinterpret_cast< QList<T const*> const& >(
        list
        );
}

形式上仍然存在reinterpret_cast潜在的问题,但是任何专门表示QList元素的常量的人都应该得到他们所得到的一切。:-)

干杯&hth.,

于 2011-06-26T10:50:45.083 回答
3

const 正确性想法很弱,您发现的原因是众多原因之一。恒定性概念仅捕获了一点语义(更改/不更改)并且做得很糟糕并且语法成本相当高,有时甚至需要重复代码。

这个概念的一个问题是它不能通过组合很好地扩展:例如,我可能有兴趣向一个函数传递一个非常量对象的常量向量,或者一个常量对象的非常量向量,或者一个常量向量const 对象和正确的语法是昂贵的......只要考虑一下标准 c++ 是如何被迫引入const_iterator的,因为这当然与const iterator.

多年来,我从狂热的立场转变为只在我被迫使用的地方使用 const 正确性。经验告诉我,不沉迷于 const 正确性的代码会变得更干净,并且 const 正确性机制从未真正捕获(至少对我而言)任何逻辑错误,而只会捕获有关 const 正确性机制本身的错误。不幸的是,const 正确性是 C++ 中你被迫使用的东西之一,因为 C++ 规则是这样说的,而且没有办法避免使用它。

我知道我会因为这篇文章而被否决,但我的建议是密切关注你在这个主题上读到的关于 C++ 的任何内容;保持头脑清醒,客观地判断。不幸的是,仅仅因为某些事情是真实的(例如, const 正确性有助于程序员)会很好,但这并不意味着它真的是真实的。

不管签书的名字有多大。

还要记住,如果一个立场要求世界上所有其他人都是错误的,那么至少有点怀疑可能是个好主意:大多数语言,即使是那些在 C++ 之后诞生的语言,都没有实现这个概念。

于 2011-06-26T11:58:43.930 回答