指向Const数据和c++列表的Const指针

const pointer to const data and c++ lists

本文关键字:Const 指针 列表 数据 指向 c++      更新时间:2023-10-16

我想在列表中插入一些元素。
我真正想做的是使用"insert3",因为它保证指针不会改变,数据也不会改变。
但是"insert2"answers"insert3"给出以下错误,而"insert1"没有:

class A
{
public:
    std::list<int*> l;
    void insert(int* const a)
    {
        l.push_back(a); //works
    }
    void insert2(const int* a)
    {
        l.push_back(a);
        /*
        no instance of overloaded function "std::list<_Ty, _Ax>::push_back [with _Ty=int *, _Ax=std::allocator<int *>]"
            matches the argument list
        */
    }
    void insert3(const int* const a)
    {
        l.push_back(a);
    }
};

谢谢你的帮助!

简短回答

您应该使用list<int const* const>作为l的类型,然后您可以使用任何插入,包括insert3

长回答

通过插入到list<int*>中,您尝试将int const*(指向const int的指针)转换为int*(指向int的指针)。

由于删除了不编辑指针目标的保证,因此这是不可隐式执行的。如果你真的想这样做,你可以使用const_cast(或c-cast),但通常抛弃const -ness是一个非常糟糕的主意(tm)。

为什么将指针本身设置为const不会改变什么

如果您使用int const* const(指向const int的const指针)使用版本3,则除了保证在insert3运行时变量a不会被更改之外,您不会得到任何更多或更少的东西。通过将指针插入到列表中,实际上是在复制它。这意味着无论a是否为const,生成的列表项都将是您在开始时指定的类型。

通过将列表设置为list<int const* const>,可以确保任何插入的指针都不能在以后被更改,并且指向它的值只能在显式地摆脱指针的const属性后才能更改。插入是可能的,因为添加const总是隐式地可能的

list改为指向const的指针:

std::list<const int*> l;

由于参数有一个指向const的指针,因此不允许通过隐式转换去除其const属性。

这是c++风格的编译时常量正确性类型系统中典型的高级"问题"之一。

如果你想在列表中存储int *指针,那么你将无法将const int *指针添加到该列表中(原因很明显)。这也将强制你所有的insert方法接受int *指针,而不是const int *指针。

我明白了,你真正想表达的是insert方法本身不改变指向的数据(它没有)。然而,正如您所看到的,insert有一些影响深远的副作用——它将指针存储在一个列表中。如果insert接受const int *指针,这可能会违反常量正确性。

换句话说,考虑insert本身在做什么是不够的,考虑insert为其他代码打开了什么可能性也很重要(在这种情况下-其他可以访问同一列表的代码)。在你的例子中,如果你的insert悄悄地接受了const int *指针,那么它打开的可能性很容易在其他代码中违反const- correct。

当然,在这种情况下,您可以通过使用强制的const_cast s来实现您自己对正确的常量正确性的看法。但是这样看起来就不好看了。