我相信,使用
C/C++
多年的人对下面这个字符串赋值语句都不会陌生吧。
同时,我也相信,各位在使用这种语句后吃过很多苦头也不少吧?只要你想利用指针
p
来改变字符串的内容,你的程序都会得到一个让你颜面尽失一个内存非法操作。比如,下面的这些语句:
原因就在于,
char* p = "test";
这个声明,声明了一个指针,而这个指针指向的是全局的
const内存区
,
const
内存区当然不会让你想改就改的。所以,如果你一定要写这块内存的话,那就是一个非常严重的内存错误。另,之所以加粗“全局
const
内存区”,是强调一下,如果你不信的话,你可以试试下面这段代码,看看
p1
和
p2
的地址是不是一样的。
我想这应该是一个众所周知的问题吧。取而代之的,应该是使用数组来做初始化声明。如:
charstr[] = “hello world”;
如果现在还有哪本书中的
C
的示例采用了使用const字符串初始化指针的这种方式,那么你就可以把那本书撕了,如果这本书是
C++
的书话,那么你应该把这个作者和这个出版社告上法庭,因为你不应该容忍这种学术骗子。如果你的部门的开发人员还有人写出这种代码的话,如果他是
C
程序员,我想你可以在打过他的屁股后告诉他下不为例,如果他是一个
C++
程序员的话,我想你可以怀疑他是否有资格做一个
C++
程序员了。
这样,当你修改这个字符串的内容时,编译器会给你一个错误而导致你的程序编译不通过,从而不会产生运行时的内存错误。
在
C++
中,比如:函数的参数和异常的捕获都存在这种问题,如下所示:(因编译器而定,在
gcc3.4.3
版中,下例中的异常示例不能被捕获,但
VC++6
中却可以被捕获)
一、 隐晦的字符串的const转换。
char *p = "test";
w_char *pw = L"test";
二、 隐晦的类型声明。
func() {} //
函数的隐晦返回类型是
int
staticnum; //
变量的隐晦类型是
int
三、 布尔变量的累加操作。
bool isConn = false;
isConn++; //
这个操作会把
isConn
变为
true
就目前而言,几乎所有的编译器都认可这种操作,但这种用法也是不被建议的,终有一天会被取消。
四、 更改父类成员的存取权限。
class B
{
};
class D : public B
{
};
五、 文件中域的static声明
static int i;
static void func()
文章到这里应该结束了,在结束之前,让我再给大家共享一个有趣的关于
const
的例子(在网上看到的)
这段代码输出的结果如下:
value a=1
value *p=2
address a=0xbff1d48c
address p=0xbff1d48c
地址都是一样的,可值为什么不一样呢?呵呵。这个问题看起来有点“学术味”过浓,不过是个好例子,可以让你知道
C++
的一些用法和一些原理。有以下几个方面大家可以考虑一下:
1)
const int a = 1
是不是和宏有点像,会不会被编译器优化了?
2)
去修改一个
const
的值,本来应该是不对的。这可能会是向旧的
C
兼容。是否会让编译器产生未知行为?
所以,这个示例也告诉我们,我们应该遵循
C++
中的
const
和
non-const
的语义,任何想要破坏这个语义的事情都会给我们带来未知的结果。
