2010-10-22 24 views
6

通过调用string :: c_str()指向的指针返回到哪里?在下面的代码片段中,我想我会得到一个分段错误,但它给了我正确的输出。如果string :: c_str()返回的指针指向字符串对象内部的位置,那么当函数返回并调用对象析构函数时,我应该得到无效的内存访问。string :: c_str查询

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

const char* func() 
{ 
    string str("test"); 
    return str.c_str(); 
} 

int main() 
{ 
    const char* p = func(); 
    cout << p << endl; 
    return 0; 
} 

Output: test 
Compiler: g++ 4.3.3 
Platform: ubuntu 2.6.28-19 

回答

13

哪里指针调用string::c_str()点回来了?

它指向在存储器中的某些地方含有std::string的内容的空终止字符串的位置。

指针仅在std::string被修改或销毁之前有效。如果您再次致电c_str()data(),它也可能失效。

基本上,你最安全的赌注是假设从c_str()获得的指针在你下一次对std::string对象做某事时失效。

我应该得到一个无效的内存访问。

不,你会得到未定义的行为。您可能会遇到某种内存访问错误(如分段错误),但是您的程序也可能会继续正常运行。它可能似乎工作一次你运行你的程序,但失败的下一个。

+0

AFAICT,'c_str()'返回的指针在下一次调用非const函数之前是有效的。由于'c_str()'和'data()'都是'const' themelves,它们可能不会使先前返回的指针无效。 – MSalters 2010-10-22 10:00:32

+1

@ MSalters:我也这么认为,但是:“引用'basic_string'序列的元素的引用,指针和迭代器可能会被以下对'basic_string'对象的使用无效:...调用'data( )'和'c_str()'成员函数“(C++ 03 21.3/5)。我会考虑将'c_str()'作为返回指向字符串中元素的指针,以便通过对'c_str()'的另一个调用使指针_could_失效。我可能是错的。 – 2010-10-22 15:34:38

+0

我认为那里的想法是,basic_string可能通过在其内部缓冲区附加一个'\ 0'来实现c_str(),并返回一个指向附加缓冲区的指针。这样的实现很少存储'\ 0',并且从不存储两个副本。您引用的文本允许这样做 - 没有指定'c_str'是否返回指向元素的指针或指向这些元素副本的指针。 – MSalters 2010-10-25 08:28:24

2

您希望打印出什么?

#include <iostream> 
#include <string> 

int main() 
{ 
    int* test = new int[20]; 
    test[15] = 5; 
    std::cout << test[15] << "\n"; 
    delete[] test; 
    std::cout << test[15] << "\n"; 
    return 0; 
} 

在2010年VS释放模式,我得到这样的结果:

释放的内存,当您尝试访问它并不一定抛出异常。该值也不一定会被重写。 (有趣的是,如果我将编译更改为调试模式,编译器会用-572662307覆盖该值)。

当您尝试访问标准时未定义什么发生。这意味着编译器可以做任何事情,或者选择什么也不做。 (或者崩溃你的程序,或者炸毁宇宙......)

+0

优秀的插图.... – Tanuj 2010-10-22 04:36:57

相关问题