【问题标题】:What is constexpr?什么是 constexpr?
【发布时间】:2016-04-28 12:00:13
【问题描述】:

好的,所以我正在阅读 C++ Primer,Fifth Editon,并且我是第一次学习 constexpr。开头是这样的:

重要的是要理解,当我们在一个 constexpr 声明,constexpr 说明符适用于指针, 不是指针指向的类型:

 const int *p = nullptr; // p is a pointer to a const
 *q = nullptr; // q is a const pointer to int

好吧,我想我自己...好吧,它 p 是一个指向 const 的指针,那么这意味着 p(指针) it-self 不是一个常数,所以我可以更改它。所以当然,我在我的 IDE 上试了一下:

#include <iostream>
#include <list>
#include <vector>
#include <string>


int main()
{
    const int x = 0;
    const int y = 30;
    const int *p = x;
    *p = &y;
    return 0;
}

你猜怎么着。当我尝试将 *p 分配给常量 y 的地址时,它给了我一个错误。那么具体的错误

error: assignment of read-only location '* p'|

哇,我很惊讶。我真的认为这本书说 p 是指向 const 的指针。所以我认为 p 不是一个常数,所以你可以改变它。?还是我的anaolgy错了??

然后它当然会告诉我:

constexpr int *q = nullptr; // q is a const pointer to int

如果我之前的类比是正确的,那么这个指针就是一个实际的 const it-self。所以它可能不会改变..?还是我错了?

constexpr

好吧,伙计们,我明白了。当我将指针分配给“对象”或任何东西时,我不应该取消引用。但是现在我第一次尝试 constexpr 时遇到了这个错误!

error: invalid conversion from 'const int*' to 'int*' [-fpermissive]|

这是我的代码:

int main()
{
    const int a = 0;
    const int i = 5;
    constexpr int *w = &a;
    return 0;
}

【问题讨论】:

  • 你的错误实际上是因为你需要将指针分配给地址一个变量:const int *p = &amp;x;当然你不能分配*p,因为结果@ 987654329@ 是常量! (更不用说您正在尝试将 const int 分配给 const int*
  • 好的,我刚刚知道了,并在我的 IDE 上快速尝试了它。但在我的 IDE 中也有同样的问题。而且我正在使用代码块,所以它可以准确地告诉我错误在哪里。当然,错误指向我声明 *p = &x @AndyG 的位置
  • 阅读对我的评论的编辑。我解决其他问题。
  • 好的,非常感谢@AndyG!当我试图分配指针时,我只是搞砸了。原来我不需要 astrix.... -.-

标签: c++ pointers constants constexpr


【解决方案1】:

你有一个错字。当您使用 *p 取消引用指针时,您可以访问您无法更改的底层 const int

p = &y;

另一方面,更改 p 指向的内容。具体来说,它将p 更改为指向y,这是合法的。

int main()
{
    const int x = 0;
    const int y = 30;
    const int *p = &x;
    std::cout << *p << "\n";
    p = &y;
    std::cout << *p;
    return 0;
}

输出:

0
30

Live Example

我也不得不改变

const int *p = x;

const int *p = &x;

否则,您将尝试使用 x 的值而不是 x 的地址来初始化指针。


您的constexpr 错误与指针的类型以及您要指向的内容有关。

constexpr int *w = &a;

说给我一个int *,让它指向a,然后把它变成constexpr。现在aconst int 而不是int 尝试这样做会删除aconst,这是非法的。

如果我们把它改成

constexpr const int *w = &a;

然后我们有正确的类型,但现在我们有一个新的错误。 a 不是constexpr,因此它不能在constexpr 初始化中使用,因为它是一个局部变量,并且在运行时只有一个地址。如果我们创建astatic 或全局变量,那么地址将在编译时已知,我们可以在constexpr 中使用它。

【讨论】:

  • 哦,非常感谢!因此,当您分配指针时,您不需要拥有 astrix。现在我不知道要接受哪个答案。因为你们俩的代码几乎相同..
  • @Dsafds 您可以接受任何您想要的答案。选择对您最有帮助的一个,并称之为好。如果您选择不同的答案,我不会感到不安。给予是你的接受。
  • 确实,选择您认为最能描述并回答您问题的内容。
  • 内森,我已经编辑了我的问题。对于多个问题,我很抱歉,但我无法得到 constexpr 的错误...?我不明白为什么我会收到错误。
【解决方案2】:

要将指针分配到变量的某个内存位置,您需要使用&amp; 地址运算符:

const int *p = &x;

第二个语句也是如此:

*p = &y;

您尝试设置变量p 指向的值而不是指针本身。

试试:

p = &y;

您不应该取消引用来设置指针的位置。星号告诉编译器返回指针指向的值,你不希望这样。

【讨论】:

  • 哦,非常感谢!因此,当您分配指针时,您不需要拥有 astrix。现在我不知道要接受哪个答案。因为你们俩的代码几乎相同..
  • 吉尔,我已经编辑了我的问题。对于多个问题,我很抱歉,但我无法得到 constexpr 的错误......?我不明白为什么我会收到错误消息。
  • @Dsafds:它被称为星号
【解决方案3】:

首先,

const int *p = nullptr;

p 是一个指向 int 的指针,它指向一个 const int。这意味着,p 可以分配为指向另一个地址,但是您不能通过取消引用 p 来更改 p 指向的对象。

int* const p = nullptr;

这里的p 是一个const 指向int 的指针。这意味着您可以通过取消引用p 来更改p 指向的对象,但是您不能更改p 指向的地址。

另一方面,constexpr 表示可以在常量表达式中使用的变量。声明为constexpr 的指针被隐式声明为const 指针。也就是说,

constexpr int* p = nullptr;

与声明有一些区别:

int * const p = nullptr;

一个重要的区别是您必须使用静态初始化器(例如,全局变量的地址)初始化 constexpr 指针。

【讨论】:

    【解决方案4】:

    恐怕你误解了这个概念,首先:

    int i, j;
    const int *ptr = &i;
    *ptr = 123; // error
    ptr = &j; // ok
    

    使ptr 成为一个指向常量数据的非常量指针,即你不能通过这个指针改变变量i,但可以改变指针本身。另一方面:

    int i, j;
    int * const ptr = &i;
    *ptr = 123; // ok
    ptr = &j; // error
    

    使ptr 成为常​​量指针,因此您可以更改i 的值但不能更改ptr 本身,并且:

    int i, j;
    const int * const ptr = &i;
    *ptr = 123; // error
    ptr = &j; // error
    

    使ptr const 指针指向 const 数据。

    constexr 另一方面是完全不同的概念——它告诉编译器值必须在编译时计算并且是常数。所以这就是为什么你不能将局部变量的地址分配给constexpr指针。

    【讨论】:

      猜你喜欢
      • 2020-05-11
      • 1970-01-01
      • 2014-02-27
      • 2020-10-30
      • 1970-01-01
      • 1970-01-01
      • 2015-02-12
      • 2021-05-07
      • 2014-05-27
      相关资源
      最近更新 更多