запрос string :: c_str - PullRequest
       2

запрос string :: c_str

6 голосов
/ 22 октября 2010

Куда указывает указатель, возвращенный вызовом 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

Ответы [ 2 ]

13 голосов
/ 22 октября 2010

Где указатель, возвращенный при вызове string::c_str(), указывает на?

Указывает на некоторое место в памяти, где строка с нулевым символом в конце, содержащая содержимое std::string, имеет видрасположен.

Указатель действителен только до тех пор, пока std::string не будет изменен или уничтожен.Он также потенциально недействителен, если вы снова позвоните c_str() или data().

По сути, ваша самая безопасная ставка - предположить, что указатель, полученный из c_str(), станет недействительным в следующий раз, когда вы сделаете что-то для std::string object.

Я должен получить недопустимый доступ к памяти.

Нет, вы получаете неопределенное поведение.Вы можете получить какую-либо ошибку доступа к памяти (например, ошибку сегментации), но ваша программа также может работать правильно.Может показаться, что сработает один раз, когда вы запустите свою программу, но в следующий раз произойдет сбой.

2 голосов
/ 22 октября 2010

Что вы ожидаете, что это распечатает?

#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).

Что происходит, когда вы пытаетесь получить к нему доступ, стандарт не определен. Это означает, что компилятор может делать все, что ему хочется, или выбирать ничего не делать. (Или сбой вашей программы, или взорвать вселенную ...)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...