我在下面的代码片段中找到了
const int i = 2;
const int* ptr1= &i;
int* ptr2 = (int*)ptr1;
*ptr2 =3;
Run Code Online (Sandbox Code Playgroud)
i价值变为3.我想知道的是为什么允许这样做.有什么情况可以变得有用?
Gra*_*and 30
这是允许的,因为你通过将它转换为非const指针来推翻ptr1的constness.这就是演员阵容非常危险的原因.
请注意,某些编译器(如GCC)不允许您像这样抛弃const状态.
dmc*_*kee 12
你通过玩指针技巧打破了恒定性保证.这不能保证一直工作,并且几乎可以调用任何行为,具体取决于您抛出它的系统/ OS /编译器.
不要那样做.
或者至少不要这样做,除非你真的知道自己在做什么,甚至理解它并不是最便携的.
Ste*_*sop 10
"允许"是"被阻止"的反对,但它也与"被禁止"相反.您已经看到,不会阻止修改您的const对象,但这并不意味着它是允许的.
在"允许"的意义上,修改const对象不是"允许的".标准没有定义程序的行为(见6.7.3/5).恰好在您的实现上,在该运行中,您看到了值3.在另一个实现或另一天,您可能会看到不同的结果.
但是,它并没有被"阻止",因为在C转换工作的方式下,在编译时检测它是一个停滞的问题.在运行时检测它需要在所有内存访问中进行额外检查.该标准旨在不对实现施加大量开销.
抛弃const的原因是支持的,因为如果你有一个指向非const对象的const指针,那么该语言允许你(在两种意义上)修改该对象.为此,您需要摆脱const限定符.这样做的结果是程序员也可以从指向实际为const的对象的指针中丢弃const限定符.
这是一个(稍微愚蠢的)代码示例,它抛弃了const限定符,原因如下:
typedef struct {
const char *stringdata;
int refcount;
} atom;
// returns const, because clients aren't allowed to directly modify atoms,
// just read them
const atom *getAtom(const char *s) {
atom *a = lookup_in_global_collection_of_atoms(s);
if (a == 0) {
// error-handling omitted
atom *a = malloc(sizeof(atom));
a->stringdata = strdup(s);
a->refcount = 1;
insert_in_global_collection_of_atoms(a);
} else {
a->refcount++;
}
return a;
}
// takes const, because that's what the client has
void derefAtom(const atom *a) {
atom *tmp = (atom*)a;
--(tmp->refcount);
if (tmp->refcount == 0) {
remove_from_global_collection_of_atoms(a);
free(atom->stringdata);
free(atom);
}
}
void refAtom(const atom *a) {
++(((atom*) a)->refcount);
}
Run Code Online (Sandbox Code Playgroud)
这很愚蠢,因为更好的设计是前向声明atom,使指针完全不透明,并提供访问字符串数据的功能.但是C并不要求你封装所有内容,它允许你返回指向完全定义类型的指针,并且它希望支持这种const用法来呈现一个"真正"可修改的对象的只读视图.
| 归档时间: |
|
| 查看次数: |
2025 次 |
| 最近记录: |