我有一篇文章,但我失去了它.它展示并描述了一些人们应该小心的C/C++技巧.其中一个让我感兴趣,但现在我正在尝试复制它,我无法将其编译.
这个概念是可以随意改变const
C/C++ 中a的值
它是这样的:
const int a = 3; // I promise I won't change a const int *ptr_to_a = &a; // I still promise I won't change a int *ptr; ptr = ptr_to_a; (*ptr) = 5; // I'm a liar; a is now 5
我想向朋友展示这个,但现在我错过了一步.有谁知道它开始编译和工作缺少什么?
ATM我从'const int*'到'int*'的转换无效,但是当我读到我试过的文章时,它运行得很好.
你需要抛弃常量:
linux ~ $ cat constTest.c #includevoid modA( int *x ) { *x = 7; } int main( void ) { const int a = 3; // I promisse i won't change a int *ptr; ptr = (int*)( &a ); printf( "A=%d\n", a ); *ptr = 5; // I'm a liar, a is now 5 printf( "A=%d\n", a ); *((int*)(&a)) = 6; printf( "A=%d\n", a ); modA( (int*)( &a )); printf( "A=%d\n", a ); return 0; } linux ~ $ gcc constTest.c -o constTest linux ~ $ ./constTest A=3 A=5 A=6 A=7 linux ~ $ g++ constTest.c -o constTest linux ~ $ ./constTest A=3 A=3 A=3 A=3
另外,常见的答案在g ++ 4.1.2中不起作用
linux ~ $ cat constTest2.cpp #includeusing namespace std; int main( void ) { const int a = 3; // I promisse i won't change a int *ptr; ptr = const_cast ( &a ); cout << "A=" << a << endl; *ptr = 5; // I'm a liar, a is now 5 cout << "A=" << a << endl; return 0; } linux ~ $ g++ constTest2.cpp -o constTest2 linux ~ $ ./constTest2 A=3 A=3 linux ~ $
顺便说一句......这是永远不推荐的...我发现g ++不允许这种情况发生..所以这可能是你遇到的问题.
只是一个猜测,但一个常见的问题是为什么一个人不能转换int**
为a const int**
,这看起来是合理的(毕竟,你只是添加一个const
,这通常是好的).原因是如果你可以这样做,你可能会意外地修改一个const
对象:
const int x = 3; int *px; const int **ppx = &px; // ERROR: conversion from 'int**' to 'const int**' *ppx = &x; // ok, assigning 'const int*' to 'const int*' *px = 4; // oops, just modified a const object
这是一个非常不直观的结果,但是确保const
在这种情况下无法修改对象的唯一方法(注意没有类型转换)是使第3行成为错误.
您只能const
在第一级间接添加时不添加强制转换:
int * const *ppx = &px; // this is ok *ppx = &x; // but now this is an error because *ppx is 'const'
在C++中,如果const
不使用某种类型的类型转换,则无法修改对象.您必须使用C风格的强制转换或C++风格const_cast
来删除const
-ness.任何其他尝试这样做都会导致编译器错误.
请注意,标准未定义任何抛弃constness的尝试.从标准的7.1.5.1开始:
除了可以修改任何声明为mutable的类成员之外,任何在其生命周期内修改const对象的尝试都会导致未定义的行为.
在使用此示例之后:
const int* ciq = new const int (3); // initialized as required int* iq = const_cast(ciq); // cast required *iq = 4; // undefined: modifies a const object
因此,简而言之,使用标准C++是不可能的.
此外,当编译器遇到类似的声明时
const int a = 3; // I promisse i won't change a
可以自由地将任何出现的'a'替换为3(实际上做同样的事情#define a 3
)
回到时间的迷雾,我们古代程序员使用FORTRAN.FORTRAN通过引用传递了所有参数,并没有进行任何类型检查.这意味着很容易意外地改变甚至是文字常量的值.您可以将"3"传递给SUBROUTINE,然后它会更改,因此每次从那时起您的代码都有一个"3",它实际上会像一个不同的值.让我告诉你,这些都是难以找到并修复的错误.