browser icon
You are using an insecure version of your web browser. Please update your browser!
Using an outdated browser makes your computer unsafe. For a safer, faster, more enjoyable user experience, please update your browser today or try a newer browser.

const 参数释疑

Posted by on 2007 年 07 月 20 日

你可以任意转载本文,但请在转载后的文章中注明作者和原始链接。
媒体约稿请联系 titilima_AT_163.com(把“_AT_”换成“@”)。

群里边有人提到了一个 const 参数问题,于是把几个要点释疑于此。老鸟们看到的话就绕道吧。
对于一个 const 参数而言,它表示在函数的作用域范围内不允许改变这个参数的值。考虑下面的代码:

1
2
3
4
5
void f1(const char* str)
{
    str[0] = 'I'; // error C2166: l-value specifies const object
    puts(str);
}

str 参数是 const char*,这表示在函数作用域范围内不可以改变 str 所指向的内容。当试图改变 str[0] 的时候,会收到一个 C2166 的编译错误。
所以说,这仅仅是一个语法层面上的限制。再考虑下面的代码:

1
2
3
4
5
6
7
8
void f2(const char* str)
{   
    const_cast<char*>(str)[0] = 'I';
    puts(str);
}
 
char str[] = "Hello, World!";
f2( str ); // "Iello, World!"

这段代码能够很好的运行,也完全达到了效果。const_cast 转换在这里发挥了作用,也就是从语法层面上绕开了 const 的限制。
但是这么做并不是被提倡的,考虑下面代码:

1
f2("Hello, World!"); // Oops!

在 Windows 环境下测试的结果是程序崩溃。因为这里虽然 const_cast 避开了编译器的检查,但它尝试改写只读内存区的内容,所以引发了一个 Access Viotation(0xC0000005)异常。
当然凡事没有什么绝对,再考虑下面的 Win32 代码:

1
2
3
4
5
6
7
8
9
10
11
12
void f3(const char* str)
{
    char *p = const_cast<char*>(str);
 
    DWORD dwOldProtect;
    VirtualProtect(p, 1, PAGE_READWRITE, &dwOldProtect);
    p[0] = 'I';
    VirtualProtect(p, 1, dwOldProtect, &dwOldProtect);
    puts(str);
}
 
f3("Hello, World!"); // "Iello, World!"

在 f3 中改变了 p 的内存页面属性使之能够读写,所以这里对 p[0] 写入的时候是一个成功的操作。不过,这终究是一个比较嘬而且很较真的方式,在此一并提出的目的是为了把孔乙己的第四个“回”字写完。

订阅本站

4 Comments

  • At 2008.02.29 13:30, mood said:

    好文。。。很强很正点。。。收了,哈哈

    • At 2008.02.29 14:07, 周伯通 said:

      好。

      • At 2010.10.13 14:42, aaxron@126.com said:

        群号多少?
        加我吧.

        • At 2010.10.13 15:34, 李马 said:

          某半荒废群,无视之即可。

          (Required)
          (Required, will not be published)