2010-10-06 82 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*)其内部缓冲区的字符串字面的副本创建。然后你返回一个指向字符串内部缓冲区的指针,该指针立即超出范围,并在函数返回时立即释放。