Проблема передачи C-строк в C ++ - PullRequest
2 голосов
/ 14 февраля 2011

Я не разработчик C ++ и пытаюсь выяснить, почему, когда я возвращаю C-строку из функции, я получаю мусор.

#include <stdio.h>

const char* tinker(const char* foo);

int main(void)
{
    const char* foo = "foo";
    foo= tinker(foo);
    printf(foo); // Prints garbage
    return 0;
}

const char* tinker(const char* foo)
{
    std::string bar(foo);
    printf(bar.c_str());  // Prints correctly
    return bar.c_str();
}

Ответы [ 6 ]

8 голосов
/ 14 февраля 2011

Вы возвращаете C-строку, основанную на внутренней памяти std::string.Однако, это печатается ПОСЛЕ того, как ваш bar уничтожен.Эта память становится мусором к тому времени, как она достигает строки printf(foo);.

4 голосов
/ 14 февраля 2011

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

Если вам нужно содержимое bar после возврата функции, верните bar вместо bar.c_str().

2 голосов
/ 14 февраля 2011

Чтобы добавить то, что говорили другие, это один из способов заставить его работать:

#include <stdio.h>

std::string tinker(const char* foo);
int main(void)
{
     const char* foo = "foo";
     std::string foo2= tinker(foo);
     printf(foo2.c_str()); // Prints correctly
     return 0;
}  

std::string tinker(const char* foo)
{     
     std::string bar(foo);
     return bar; 
} 

Здесь объект std :: string копируется * через возвращаемое значение, и вы печатаете копиюmain ().

* популярные реализации строк используют такие оптимизации, как подсчет ссылок, которые позволяют избежать фактического копирования строки.Кроме того, в C ++ 0x строковый объект будет перемещен, а не скопирован.

1 голос
/ 14 февраля 2011

Потому что бар живет в стеке тинкера;после выхода из функции ее c_str () исчезает.

1 голос
/ 14 февраля 2011
return bar.c_str();

Эта строка возвращает char* временного объекта, который удаляется в конце функции, и поэтому в main () foo указывает на удаленный объект char*.

1 голос
/ 14 февраля 2011

Потому что вы выделяете бар в стеке тинкера.Когда тинкер заканчивается, его стек восстанавливается, строка удаляется, поэтому указатель, который вы возвращаете, указывает на освобожденную память, то есть он больше не действует при выходе из функции.

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