C 与 C++ 中的常量正确性
Const correctness in C vs C++
我理解常量正确性的含义,我的问题不是关于常量正确性是什么。所以我不期待对此的解释或C++常见问题解答链接。
我的问题是:
-
C 语言中的
const
和 C++ 中的const
之间的语义差异是什么? - 差异的原因是什么?
各个标准中引用明确差异会很好。
我经常在 C 和 C++ 之间切换,我想知道在这样做时应该记住的要点。
我似乎不记得这些原因(如果你能提供一个理由,特别感谢(,但从我的脑海中,我记得:
- C++中的常量变量默认具有内部链接,而在 C 中它们具有默认的外部链接;
- const 对象在 C++ 中可以用作编译时值,但在 C 语言中不能用作编译时值;
- 指向字符串文字的指针必须是C++
char const*
,但在 C 中它可以是char*
。
我错过了什么?
除了您引用的差异,以及库的差异史蒂夫·杰索普提到,
char* p1;
char const* const* p2 = &p1;
在C++中是合法的,但在 C 中不是。 从历史上看,这是因为 C最初允许:
char* p1;
char const** p2 = &p1;
在标准采用前不久,有人意识到这一点在 CONST 安全中打了一个洞(因为现在可以分配*p2
char const*
,这导致p1
被分配一个char const*
(;跟没有实时深入分析问题,C委员会禁止任何除顶级常量外的其他const
。 (即 &p1
可以是分配给char **
或char **const
,但不分配给char const**
也不是char const* const*
。 C++委员会做得更远分析,意识到问题仅在const
时才存在水平之后是非const
水平,并制定了必要的措词。 (参见标准中的 §4.4/4。
const
声明中不生成常量表达式,即在 C 中,您不能在大小写标签中使用 const int
对象作为位字段宽度或非 VLA 数组声明中的数组大小(所有这些都可以在C++中实现(。此外,const 对象在 C 中默认具有外部链接(C++ 中的内部链接(。C++语言的常量正确性规则支持以下标准转换
int **pp = 0;
const int *const *cpp = pp; // OK in C++
int ***ppp = 0;
int *const *const *cppp = ppp; // OK in C++
这些在 c 中不起作用。
其中一些差异的原因是允许我们摆脱预处理器宏,这是 Bjarne 早期的设计目标之一。
在 C 中,我们可能有
#define MAX_FOOS 10
int foos[MAX_FOOS];
在C++我们希望能够写作
const int max_foos = 10;
int foos[max_foos];
要使其正常工作max_foos
需要在常量表达式中使用。它还需要具有内部链接,因此定义可以出现在标头中而不会引起多个定义错误,更重要的是使编译器更容易不为max_foos
分配任何存储空间。
当 C 委员会从 C++ 中采用 const 时,他们没有采用对宏的反感,所以他们不需要这些语义。
- 代理对象的常量正确性
- std::函数常量正确性未遵循
- C++ 常量正确性/缺少支持常量和非常量实例的类的常量构造函数
- 自定义引用包装器的常量正确性
- 如果我公开常量和非常量 API,我是否破坏了常量正确性?
- 如何强制实施有关指针数据成员的常量正确性
- 如何在C++的多维地图中实现常量正确性
- C++ 函数参数或声明中的常量正确性
- 结构初始化中的常量正确性
- 常量正确性编译错误到模板函数中的无效转换错误
- 如何在不违反常量正确性的情况下使用 std::lock_guard
- 非平凡变量的常量正确性
- 常量正确性和成员参考
- 常量正确性和shared_ptr,一个设计问题
- 观察者常量正确性
- 如何跨指针保持常量正确性
- 为了速度牺牲常量正确性可以吗
- file read()常量正确性
- C++NULL指针和常量正确性
- 共享指针和常量正确性