Возврат указателя на Char без кучи

Я работал над программой и заметил кое-что, что не имело для меня особого смысла. std::string имеет функцию c_str(), которая возвращает строковое представление в стиле C (заканчивающееся NULL) объекта std::string. Что для меня не имеет смысла, так это то, как функция c_str() может вернуть const char *, не выделяя его в кучу. Функция, по-видимому, возвращает массив символов в стеке.

Я всегда думал, что функция может возвращать правильный указатель только в том случае, если значение, на которое она указывает, было выделено в куче с помощью такой функции, как malloc() или calloc().

Как c_str() может вернуть строку без использования кучи, и могу ли я как-то имитировать такое же поведение в своем собственном коде?

Спасибо всем заранее.


person Spencer D    schedule 19.02.2015    source источник
comment
См. здесь, возможно: stackoverflow.com /вопросы/28596945/   -  person πάντα ῥεῖ    schedule 19.02.2015
comment
Спасибо, я посмотрю на это.   -  person Spencer D    schedule 19.02.2015


Ответы (3)


Указатели могут указывать на любую переменную, будь то в куче или стеке. c_str возвращает указатель на внутренний буфер строкового объекта. Обычно это в куче, однако некоторые компиляторы по своему усмотрению могут вместо этого помещать данные небольших строк в стек. Но как узнать, что возвращенный указатель находится в стеке, а не в куче?

Я не уверен, что именно вы хотите имитировать в своем собственном коде.

person Neil Kirk    schedule 19.02.2015
comment
Ну, я не знаю, действительно ли это в стеке или в куче, однако я предположил стек, потому что вам не нужно освобождать возвращаемую переменную. Так сказать спасибо за информацию. Мне придется прочитать о внутренних буферах. То, что я надеялся имитировать, — это возврат указателей на объекты без необходимости их malloc или объявления их как new. - person Spencer D; 19.02.2015
comment
Строковый объект news данные внутренне и его деструктор будет delete данные, когда строковый объект автоматически выходит из области видимости. c_str не возвращает новые данные, а только позволяет взглянуть на уже существующие данные. - person Neil Kirk; 19.02.2015
comment
О, хорошо, это имеет больше смысла. Итак, для упрощения, будет ли это похоже на систему сбора мусора? (Ограничено, конечно, только внутренним буфером.) - person Spencer D; 19.02.2015
comment
Да, в некотором роде. Современный C++ уменьшает потребность в ручном управлении памятью, например new и malloc, за счет использования стандартных контейнеров и интеллектуальных указателей. Это приводит к более безопасному коду, который не допускает утечки памяти. - person Neil Kirk; 19.02.2015
comment
Большое спасибо, это здорово знать. - person Spencer D; 19.02.2015

Указатель, возвращаемый c_str(), на самом деле является внутренним указателем на память буфера строки (которая уже была выделена в куче). Таким образом, ему не нужно выделять какую-либо (новую) память. Память уже выделена и именно так строковый объект хранит свои данные.

Вот почему указатель, возвращаемый c_str(), является недействительным после изменения строки: поскольку он указывает на внутренний буфер, этот буфер может стать недействительным после манипуляции.

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

  • Передача неконстантной ссылки на строку любой стандартной библиотечной функции или
  • Вызов неконстантных функций-членов для строки, за исключением operator[], at(), front(), back(), begin(), rbegin(), end() и rend().

Обратите внимание, что начиная с C++11, c_str() и data() выполняют одну и ту же функцию. , и он работает аналогично тому, как работает член std::vector data().

person Cornstalks    schedule 19.02.2015
comment
Спасибо за ответ и дополнительную информацию. Это проясняет большую часть моей путаницы. - person Spencer D; 19.02.2015
comment
(which has already been allocated on the heap) Возможно, нет, в зависимости от того, использует ли std::string оптимизацию коротких строк. - person PaulMcKenzie; 19.02.2015

Вот пример функции, возвращающей указатель на что-то, кроме кучи или стека:

char const * Hello(void)
{
  static const char hello_text[] = "Hello";
  return &hello_text[0];
}

Поскольку переменная была объявлена ​​как static, она будет существовать после того, как выполнение покинет функцию. Поэтому возврат указателя на это значение вполне допустим.

person Thomas Matthews    schedule 19.02.2015