【问题标题】:string::c_str querystring::c_str 查询
【发布时间】:2010-10-22 04:19:00
【问题描述】:

调用string::c_str()返回的指针指向哪里?在下面的代码 sn-p 中,我认为我会得到一个分段错误,但它给了我正确的输出。如果 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

【问题讨论】:

    标签: c++ string


    【解决方案1】:

    调用string::c_str()返回的指针指向哪里?

    它指向内存中某个包含std::string 内容的空终止字符串所在的位置。

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

    基本上,您最安全的选择是假设下次您对std::string 对象执行操作时,从c_str() 获得的指针无效。

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

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

    【讨论】:

    • AFAICT,c_str() 返回的指针在下一次调用非常量函数之前有效。由于c_str()data() 都是const 主题,它们可能不会使之前返回的指针无效。
    • @MSalters:我也这么认为,但是:“引用basic_string 序列的元素的引用、指针和迭代器可能会因该basic_string 对象的以下用途而失效: ... 调用 data()c_str() 成员函数”(C++03 21.3/5)。我会将c_str() 视为返回指向字符串中某个元素的指针,以便指针可以 被另一个对c_str() 的调用无效。我可能错了。
    • 我认为basic_string 可以通过将\0 附加到其内部缓冲区并返回指向该附加缓冲区的指针来实现c_str()。这样的实现很少会存储\0,并且永远不会存储两个副本。您引用的文本允许这样做 - 未指定 c_str 是返回指向元素的指针还是指向这些元素的副本的指针。
    【解决方案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;
    }
    

    在 VS 2010 的发布模式下,我得到以下结果:

    5
    5

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-04-17
      • 2021-06-30
      • 2023-01-11
      • 1970-01-01
      • 2013-08-31
      • 1970-01-01
      相关资源
      最近更新 更多