c++ - 关于不要返回局部对象的引用或指针的疑问 ? //c primer中文版 201页
怪我咯
怪我咯 2017-04-17 13:41:53
0
2
674

1问题

c++primer中文版201页说函数不能返回局部对象的指针或引用。

const string &manip()
{
    string ret;
    if(!ret.empty())
        return ret;      //错误返回局部对象的引用 
    else
       return "empty";   //错误 “empty”是一个局部临时量
 }

我在essential c++看到了这样的代码,函数可以返回局部变量的char 指针 和const char *,这是为什么呢?(在win7 + vs2010下编译通过并可以运行打印"num_sequence")

#include <iostream>
#include <string>
using namespace std;

    class num_sequence{
    public:
        virtual const char *what_am_i( ) const// 返回值char * 和const char*可以编译通过
        {
            return "num_sequence";
        }
    };
    int main()
    {
        num_sequence p;
        std::cout<<p.what_am_i();
    }

2进一步提问

把函数返回值有const char改为char 也可以编译通过,但不能通过char指针修改字符串的内容。


    virtual char *what_am_i( ) const//把函数返回值有const char*改为char *也可以编译通过
    {
        return "num_sequence";
    }
    

问题2我好像了解了,类似于char* p= “safdsaf”;也是不能通过指针修改rodata里的内容的。

3 希望有人帮我解释下,标题1 的内容。

怪我咯
怪我咯

走同样的路,发现不同的人生

全部回覆(2)
PHPzhong
const string &manip()
{
    string ret;
    if(!ret.empty())
        return ret;      //错误返回局部对象的引用 
    else
       return "empty";   //错误 “empty”是一个局部临时量
 }

上面兩個都是回傳的臨時變數(return "empty"先建構一個暫時的string,再回傳),在函數呼叫結束的時候就**析構了。所以是不安全的。編譯是可以通過的,但是對於傳回的結果,因為已經析構,所以是不應該使用的。

        virtual const char *what_am_i( ) const// 返回值char * 和const char*可以编译通过
        {
            return "num_sequence";
        }

上面回傳的是一個指針,指向字串"num_sequence",這個字串是在全域靜態區,是一直存在的,不是臨時的,所以沒有問題。

對於問題2

其實是不論返回的是char*還是const char*你都是不能修改的,因為其指向的是一個常數字串。強行修改會在運行時報錯。

Ty80

樓上回答的也比較清楚了,你需要了解下進程的記憶體佈局。
一般認為進程的記憶體佈局包含的區域有:
1)代碼區
2)文字常數區
3) 全域區/靜態區
4) 堆區
5 ) 堆疊區
可參考http://blog.csdn.net/duyiwuer2009/article/details/7994091
所以,你看下面的例子,只要引用的是常數區的字串相同,那麼他們的地址值就是一樣的,而不是建構一個物件。

#include <stdio.h>
#include <string>
using std::string;

void foo(){
    char * a = (char*)"hello world";
    printf("%p\n", a);;
}

void foo2(){
    const char * b = "hello world";
    printf("%p\n", b);
}

int main(){
    foo();
    foo2();
    return 0;
}

我的電腦上輸出

0x100403031
0x100403031

而對於你的問題1,

const string &manip()
{
    string ret;
    if(!ret.empty())
        return ret;      //错误返回局部对象的引用 
    else
       return "empty";   //错误 “empty”是一个局部临时量
 }
   

因為傳回型別是常數引用,而傳回的實際值是一個常數字串,在這個過程中會先建構一個臨時變量,內容為"empty",型別為string,然後再傳回給呼叫者,在返回的過程中,這個臨時變數就被釋放了,你繼續存取有可能存取成功,也可能不成功,但不管怎麼樣,資料已經是一個髒資料了,這種行為C++沒有規定一定是程式崩潰或不崩潰,統一稱為未定義的行為,由運行上下文來定,是否崩潰。

熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板