【问题标题】:Why can't a const pointer be set afterwards?为什么之后不能设置 const 指针?
【发布时间】:2015-11-04 18:39:15
【问题描述】:

我知道这可能是一个微不足道的问题。声明后无法设置 const 指针的逻辑是什么?分配内存不会改变 const 所指的起始地址。那为什么不能这样……

int* const p;
p = new int [10];

...完成...这也禁止将 const 指针传递给函数?

【问题讨论】:

  • 你不将new 调用返回的指针分配p 吗?因此,显然您正在更改它指向的地址。我不明白您所说的“禁止将 const 指针传递给函数”是什么意思。
  • 对。但是第一个值是未定义的。所以就好像指针没有一个重要的值。第一个计数的值是分配期间给出的值。所以我要问的是,ONE 赋值是在声明期间还是在后面的行完成,为什么重要?无论如何,只有一项正式任务。
  • @dspfnder C++ 没有默认初始化值是“计数”还是有效的概念。这就是 Clang 禁止在没有显式初始化的情况下创建 const 值的原因。
  • @dspfnder: “ONE 赋值是在声明期间还是在后面的行完成有什么关系?” 因为那不是真的。 “声明期间的赋值”不是赋值。这是一个初始化。
  • @dspfnder 你有 Java 背景吗? C++ 中的 const 指针不等同于 Java 中的 final 引用。

标签: c++ function pointers constants


【解决方案1】:

这就是const的全部目的。

const代表“常量”,表示对象不能被赋值。

如果您希望指针成为变量,请不要将其设为const

我怀疑您希望您的分配被允许,因为这是对该对象的第一次分配。你错了!这是初始化的目的,你目前没有使用它。

我猜你打算写:

int* const p = new int[10];

但我担心你在这里有更多基本的误解。例如:

分配内存不会改变起始地址

是的,绝对,完全会。

当您的p 出现时,它具有未指定的值。它的值不是你可以使用的“起始地址”。

然后你分配给它(尽管你应该已经初始化了)。它的值等于new 返回的指针。该指针与代码中之前的任何内容都没有关系。

【讨论】:

    【解决方案2】:

    分配内存确实会改变地址。例如,如果我们有

    int * foo;
    foo = new int[bar];
    

    foo 未初始化并具有垃圾值。然后foo = new int[bar]; 分配给foo 一个新地址,该地址是bar ints 块的开始。

    现在当你有

    int* const p;
    

    指针是const,所以初始化后就不能修改了。

    【讨论】:

    • “它存储一些地址”并不是描述未初始化指针的准确方法。从未初始化的值中读取是非法的,如果这样做,两次读取同一变量可能不会返回相同的地址。
    • @BenVoigt 这个更好吗?
    • 实际上int* const p; 行甚至无法编译,因为您不能声明const 并使其未初始化。
    【解决方案3】:

    短版

    你定义指针的方式意味着它本身就是const,所以你不能重新分配它,你实际上必须连同它的声明一起分配它

    Here 更多关于 const 关键字的详细信息,尽管它并不是专门针对指针的使用。

    请注意,以下代码不应该编译,因为你没有为 const 指针赋值 p:

    int main() {
        int * const p;
    }
    

    下面的也一样:

    int main() {
        int const i;
    }
    

    这并不取决于您处理的是指针这一事实,而是const 关键字的实际工作方式和应该/可以使用的方式。


    关于 const 和指针的更多细节

    无论如何,我没有看到你的整个代码,在我看来你的意图不是有一个 const 指针,而是在你的情况下它可以帮助有一个指向 const 的指针(但这主要取决于你的问题,所以我可能是错的)。 当然,如何定义它们取决于您的目的。

    你可以将它定义为一个 const 指针或一个指向 const 值的指针,它们的方式略有不同(当然,你也可以将指针定义为一个指向 const 值的 const 指针,这很容易上述其他人的可推论结果)。

    第一个表示指针本身不能重新分配,因此您必须在声明期间对其进行分配,仅此而已。 第二个是定义一个可重新分配的指针,但您可以只分配给定类型的 const 变量的地址(或者更好,即使它们被定义为非 const,当通过该指针访问时,它们也将被视为 const,具有案例的所有限制)。

    下面是上面提到的 const 指针和指向 const 的指针类型的一个简单例子:

    int main() {
        int i;
        // pointer to const int
        int const *icp;
        // const pointer to int
        int * const cip = &i;
        // const pointer to const int
        int const * const cicp = &i;
        // this one can be reassigned, of course
        icp = &i;
    }
    

    还要注意int constconst int 是可以互换的,所以下面的声明是等价的:

    int const *p;
    const int *p;
    

    显然,这不是一份详尽的清单。我只是试图为您提供更多关于在定义指针时如何使用 const 关键字以及这些声明的预期方式的详细信息。

    【讨论】:

    • 我知道 const 指针和指向 const 的指针之间的区别。我的问题专门针对第一个案例。既然它的初始值基本上是一个非值,为什么不应该让你给它赋一次真正的值呢?
    • 回复中多次说明,不能修改。因此,您必须在声明期间分配一个值。
    • 只是澄清您的回复中的一些困惑。谢谢。
    • 我很高兴,但请让我知道有什么不清楚的地方。澄清一下没问题。
    • @dspfnder:它的初始值不是“基本上是非值”。我不知道你在哪里听说过。这是一个未指定的值。
    【解决方案4】:
    int* const p;
    

    声明p 是一个无法更改的指针,即一旦初始化,您就无法更改它指向的位置。但是,您可以更改它指向的值,因为它指向的对象类型是int

    int* const p = new int [10];
    p = new int[20]; // Not OK
    p[0] = 100;      // OK
    

    对比

    int const* p = new int [10];
    p = new int[20]; // OK. You can change where the pointer points to.
    p[0] = 100;      // Not OK. You cannot change the value of what p points to.
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-01-10
      • 2014-05-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-16
      • 2010-10-16
      相关资源
      最近更新 更多