什么是constexpr?

时间:2016-04-28 12:00:13

标签: c++ pointers const constexpr

好的,所以我正在阅读C ++ Primer,Fifth Editon和我第一次学习constexpr。首先说:

  

重要的是要理解当我们在a中定义指针时   constexpr声明,constexpr说明符适用于指针,   不是指针指向的类型:

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

好吧,我想我自己......好吧,它是一个指向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不是一个恒定的自我,所以你可以改变它。或者我的厌恶是错误的吗?

然后它告诉我:

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

如果我以前的anaology是正确的那么,这个指针实际上是const-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;
}

4 个答案:

答案 0 :(得分:4)

你有一个错字。当您*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尝试这样做会删除const a这是非法的。

如果我们将其更改为

constexpr const int *w = &a;

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

答案 1 :(得分:3)

要为变量的某个内存位置指定一个指针,需要使用&地址运算符:

const int *p = &x;

同样适用于第二个陈述:

*p = &y;

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

尝试:

p = &y;

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

答案 2 :(得分:0)

首先,

const int *p = nullptr;

p是指向int指向const int的指针。这意味着,p可以指定为指向另一个地址,但是您无法通过解除引用p来更改p指向的对象。

int* const p = nullptr;

此处p是指向const的{​​{1}}指针。这意味着您可以通过解除引用int来更改p指向的对象,但是您无法更改p指向的地址。

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

const

与声明相同的一些差异:

constexpr int* p = nullptr;

一个重要的区别是您必须使用静态初始化程序(例如,全局变量的地址)初始化int * const p = nullptr; 指针。

答案 3 :(得分:0)

首先,我担心你会误解这个概念:

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

使ptr成为const数据的非常量指针,即您不能通过此指针更改变量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指针。