2009年11月13日 星期五

C++ Programming: Call by Reference/Value/Pointer and const_cast

昨天晚上 H4 的聚會上面在討論這個問題
所以寫了一小段 C++ 程式碼來作實驗
/* main.cpp */
#include <iostream>

using namespace std;

void funcA(int&);
void funcB(int);
void funcC(int*);

int main(int argc, char* argv[])
{
    int value = 10;
    cout << value << endl;
    funcA(value);
    cout << value << endl;
    funcB(value);
    cout << value << endl;
    funcC(&value);
    cout << value << endl;
    return 0;
}

/* Call by reference */
void funcA(int& value)
{
    value = 20;
}

/* Call by value */
void funcB(int value)
{
    value = 30;
}

/* Call by pointer/address */
void funcC(int* value)
{
    *value = 40;
}
將上面這段程式碼儲存成 main.cpp
再使用 GCC 編譯執行
$ g++ -Wall -g main.cpp -o main
$ ./main
10
20
20
40
對照程式碼應該就可以看出這三者之間的差異了

不過後來有人有提到 const 的問題
於是將程式碼改寫成
#include <iostream>

using namespace std;

void funcA(const int&);
void funcB(int);
void funcC(const int*);

int main(int argc, char* argv[])
{
    const int value = 10;
    cout << value << " " << &value << endl;
    funcA(value);
    cout << value << " " << &value << endl;
    funcB(value);
    cout << value << " " << &value << endl;
    funcC(&value);
    cout << value << " " << &value << endl;
    return 0;
}

/* Call by reference */
void funcA(const int& value)
{
    int &tmp = const_cast<int&>(value);
    tmp = 20;
    cout << "\t" << value << " " << &value << endl;
}

/* Call by value */
void funcB(int value)
{
    value = 30;
    cout << "\t" << value << " " << &value << endl;
}

/* Call by pointer/address */
void funcC(const int* value)
{
    int* tmp = const_cast<int*>(value);
    *tmp = 40;
    cout << "\t" << *value << " " << value << endl;
}
編譯執行的結果為
$ ./main
10 0xbfb17040
    20 0xbfb17040
10 0xbfb17040
    30 0xbfb17020
10 0xbfb17040
    40 0xbfb17040
10 0xbfb17040
為什麼會這樣呢?

3 則留言:

fr3@K 提到...

I was going to post my comment here, but it got too long...

czchen 提到...

Because this is undefined behavior.

From ISO/IEC 14882 [dcl.type.cv]

Except that any class member declared mutable can be modified, any attempt to modify a const object during its lifetime results in undefined behavior.

匿名 提到...

main::value 是一個 alias, compiler (g++ 4.3.4) 會替換成 integral literal,但是依然會在 Stack 中配置此變數供人使用。因此你可以對其寫入 (as memory/stack),惟讀取時依然讀 integral literal.

其他討論請見 http://hackingthursday.wikidot.com/2009-11-12