Re: [问题] constexpr 使用的时机

楼主: lovejomi (JOMI)   2018-07-09 22:32:05
我看到这篇
其中他说
constexpr char* p = “...“;
constexpr char* const p = ”...”;
are equivalent
于是我google了一下好像没有找到
原本我以为这边的constexpr是修饰char....原来是修饰 ”变量”也就是pointer..
我想请问
这样意思是 compile time就能决定p
指向的位址?
为什么能够决定呀?
难道程式被load到memory, "p"的虚拟内存的位址都会一样?
但实际上每次执行印出来的位址也都不一样。https://ideone.com/e2fJF0
到底constexpr在这边是在描述什么.
char* constexpr p 这样写是不是比较好读呢?可是竟然编译不过.
谢谢
※ 引述《Feis (永远睡不着 @@)》之铭言:
: ※ 引述《wtchen (没有存在感的人)》之铭言:
: : 刚刚学到constexpr这个关键字,不过看了很久不是很了解使用的时机。
: : 依照这个网页:
: : http://en.cppreference.com/w/cpp/language/constant_expression
: : 似乎是可以在等号右边放function的const?
: : 不知道前辈们有无进一步的见解?
: : 感谢。
: 大致上 http://en.cppreference.com/w/cpp/language/constexpr 写得还蛮清楚的

: 原本也想试着把整个 "常数表示式" (constant expression) 的脉络解释清楚,但是
: 发现我写了几千字还没写完就放弃了,所以下面先试着讲重点。
: 对常数表示式只要先记得一个重点: 常数表示式的值可以在编译期被算出,然后当作
: 一个常数用。
: 而被 constexpr 所指示的对象就表示该对象的值可以在编译期被算出 [注1],然后

: 作一个常数用。
: 接着我们就可以来讲一下 const 跟 constexpr 的不同。
: 我觉得需要另外发明 constexpr 这个关键字的重点是下面两个:
: 1. const 的修饰对象是型别,constexpr 的指示对象是变量或函式名。
: 2. constexpr 规范的是在编译期 (compile time) 可决定的常数值,而 const 规范
: 的是在执行期 (runtime) 决定的常数值,两者描述的是不同的概念。
: 会对 const 跟 constexpr 使用有疑惑主要是因为下面两个延伸规则:
: 规则一: 当 constexpr 指示的对象是变量名时, 就意味着该变量的型别被 const 修
: 饰。例如:
: constexpr int a = 3;
: 就等同于:
: constexpr const int a = 3;
: 规则二: 当变量型别被 const 修饰且其值是常数表示式 (编译期就可以决定的值)
: 时,就意味着该变量名有 constexpr 指示符。例如:
: const int a = 3;
: 就等同于
: constexpr const int a = 3
: 这两个规则让我们觉得 const 跟 constexpr 用谁都可以。
: 而问题在于 const int a 并不永远等同 constexpr const int a,因为 const 只保
: 证了执行期的常数性质,不保证其值在编译期可决定。
: 下面是个反例:
: int b = 3;
: const int a = b; // 不能写成 constexpr const int a = b;
: 换句话说,虽然我们知道 a 应该就是 3 了。但是因为语法上没有强制性 (例如可能
: 某个神祕的地方会偷改到 b 的值),所以这里的 a 不能当编译期的常数用。例如下
: 面这个例子是不合法的:
: int b = 3;
: const int a = b;
: int c[a]; // 在有 runtime-sized array 的 C++14 以前,这里因为 a 不
: // 是常数表示式所以在标准里是不合法的 (除非你使用 VLA 相
: // 关 Extension)。
: 但是改成下面这样又可以:
: const int b = 3;
: const int a = b;
: int c[a]; // 这里的 a 会被成功当作常数表示式作为阵列大小使用
: 原因可以由上面提过的延伸规则二知道,
: const int b = 3; 等同 constexpr const int b = 3;
: 因为 b 被 constexpr 指示是编译期可以决定的常数值,
: 所以 const int a = b; 又等同 constexpr const int a = b;
: 因为 a 被 constexpr 指示是编译期可以决定的常数值,就可以用来作为
: 阵列大小使用。
: 这一切真是太隐晦了!
: 如果当初明确的使用 constexpr指示,则编译器就会帮你确定是否该值是可以在编译
: 期决定。例如我觉得变量 a 的值应该是在编译期可以决定的常数值,那我就写成
: constexpr int a,这样编译器就会帮你检查 a 所设定的值是否是个常数表示式。
: 例如:
: int b = 3;
: constexpr int a = b; // 跟 const int a = b 不同,这样写是不合法的。因为你
: // 说 a 应该是个编译期可以决定的常数值,但是编译器从
: // 语法上不认为。
: 因为编译错误,所以我们就知道应该要改写成:
: constexpr int b = 3;
: constexpr int a = b;
: 至于这里要不要加 const 我是觉得有点多此一举所以主观的就不加了。
: 结论就是, 如果常数值是在编译期可以决定的, 就用 constexpr。
: 而使用在函式的基本概念也是一样的,只是不同的 C++ 版本有些差异,细节太多如
: 果有人有兴趣我再写看看吧。
: PS: 这里是从 C++ 出发, 在 C 里面对于 "常数表示式" (constant expression)
: 和 const 的使用很多都不一样。
: 注1: 严格来说应该写成 "有可能"
作者: sarafciel (Cattuz)   2018-07-09 23:12:00
google ASLRBTW 为什么编译期可决定置底十诫第四有回答到而你也说了这边的constexpr是修饰ptr所以根据第四条 应该宣告成constexpr const char*才对
楼主: lovejomi (JOMI)   2018-07-10 01:35:00
修饰ptr ,不是应该右边读到左边吗我知道字串常数,但既然constexpr修饰ptr,我能解读他指向的address compile time能决定好?
作者: Fenikso (薪水小偷)   2018-07-10 01:48:00
不行, constexpr只代表 "compile time能决定它指向什么东西", 无法决定address需要知道真的addr的运算都被排除在constexpr之外了
作者: soheadsome (师大狗鼻哥)   2018-07-10 08:25:00
string literal放的位置 在compile time 决定但是你整个binary 的addr则是loading才决定,应该说literal在binary中的offset.offset是compile time决定

Links booklink

Contact Us: admin [ a t ] ucptt.com