2010-10-06 81 views
7

我需要照顧內存分配,範圍和刪除關於C++「string」對象嗎?C++字符串分配

例如:

#include <string> 

const char* func1() { 
    const char* s = "this is a literal string"; 
    return s; 
} 

string func2() { 
    std::string s = "this is a literal string"; 
    return s; 
} 

const char* func3() { 
    std::string s = "this is a literal string"; 
    return s.c_str(); 
} 

void func() { 
    const char* s1 = func1(); 
    std::string s2 = func2(); 
    const char* s3 = func3(); 

    delete s1; //? 
    delete s3; //? 
} 

FUNC2:我不需要 '刪除' S2。 func3:我需要'刪除s3'嗎?

順便說一句,func1是否正確?字符內存內容在離開func1範圍後仍然可用嗎?如果是的話,我應該刪除它,當我不再需要它了嗎?

+0

http://stackoverflow.com/questions/2579874/lifetime-of-a-const-string-literal-returned-by-a-function – elgcom 2010-10-06 14:14:51

+0

http://stackoverflow.com/questions/267114/scope-of -string-literals – elgcom 2010-10-06 14:15:31

回答

16
  • func1()返回一個指向字符串文字。您不得刪除字符串文字。
  • func2()(想必,您省略了前綴std::)返回std::string。它照顧自己。
  • func3()返回一個指針,指向由函數退出時銷燬的std::string對象管理的字符串。函數返回後,請勿觸摸該指針。
  • 你將不得不採取這個函數返回的內存的護理:

    const char* func4() { 
        char* s = new char[100]; 
        // fill char array with a string 
        return s; 
    } 
    

然而,手動資源管理是棘手的。對於初學者來說,如果一個函數返回一個裸指針,你不知道它是否指向一個對象(char)或它的一個數組,以及是否需要刪除它。你應該避免這一切,只需堅持std::string

+0

現在它確定,它不是之前:) – 2010-10-06 14:14:30

+0

沒有,我可以看到。 – 2010-10-06 14:16:17

3

你對s3有一個不同的問題,即函數func3()返回一個指向當函數返回時超出範圍的對象的指針。別。

澄清:func3()中的本地字符串對象在函數返回時將不再存在,因此不需要刪除。但是,你仍然有一個指向它返回的內部緩衝區的指針。你不能使用它。

這裏非常好,詳細回答過去,免得更多的困惑隨之而來:Is it more efficient to return a const reference

+0

@Alexander Rautenberg - 最好是讓他使用s3的引用,而不是指針。反正它是正確的。 – DumbCoder 2010-10-07 12:55:57

+0

如果使用指針或引用,則func3()或s3的問題仍然存在。 func3()編碼的方式沒有任何正確的。 – 2010-10-07 15:23:14

+0

@Alexander Rautenberg - 如果您檢查正確,請勿在參考中使用字符串。返回一個對象,但將它綁定到一個const對象會增加它的生命週期,直到程序退出。如果他返回一個字符串而不是一個字符指針,他很好。 – DumbCoder 2010-10-07 15:56:17

1

我剪掉的相關代碼到其返回值的每個功能和治療,以下評論:

const char* func1() { 
    const char* s = "this is a literal string"; 
    return s; 
} 
const char* s1 = func1(); 
delete s1; //? 

您不能刪除s1,爲字符串它指向並不在堆中生活。

string func2() { 
    string s = "this is a literal string"; 
    return s; 
} 
string s2 = func2(); 

這很好。 func2s超出範圍並清理。 s2將從s複製字符串,並在func的末尾清除自身。

const char* func3() { 
    string s = "this is a literal string"; 
    return s.c_str(); 
} 
const char* s3 = func3(); 
delete s3; //? 

func3返回指向已被釋放的字符串的指針。執行delete s3後,您將獲得雙倍免費例外。

1

在FUNC3您的字符串地方由編譯器調用隱式構造函數初始化string(const char*)其內部緩衝區的字符串字面的副本創建。然後你返回一個指向字符串內部緩衝區的指針,該指針立即超出範圍,並在函數返回時立即釋放。