Возвращение c_str из функции - PullRequest
8 голосов
/ 17 апреля 2010

Это из небольшой библиотеки, которую я нашел в Интернете:

const char* GetHandStateBrief(const PostFlopState* state)
{
    static std::ostringstream out;

    // ... rest of the function ...

    return out.str().c_str()
}

В моем коде я делаю это:

const char *d = GetHandStateBrief(&post);
std::cout<< d << std::endl;

Теперь сначала d содержит мусор. Затем я понял, что строка C, которую я получаю от функции, уничтожается, когда функция возвращается, потому что std::ostringstream размещено в стеке. И я добавил:

return strdup( out.str().c_str());

И теперь я могу получить нужный текст из функции.

У меня два вопроса:

  1. Правильно ли я понимаю?

  2. Позже я заметил, что out (типа std::ostringstream) было выделено со статическим хранилищем. Не означает ли это, что объект должен оставаться в памяти до завершения программы? И если так, то почему нельзя получить доступ к строке?

Ответы [ 4 ]

11 голосов
/ 17 апреля 2010

strdup выделяет копию строки в куче, которую вы должны вручную освободить позже (я думаю, с free()). Если у вас есть возможность, было бы намного лучше вернуть std::string.

Статическое хранилище out не помогает, потому что .str() возвращает временное std::string, которое уничтожается при выходе из функции.

3 голосов
/ 17 апреля 2010

Вы правы, что out - статическая переменная, размещенная в сегменте данных. Но out.str() - это временное выделение в стеке. Поэтому, когда вы делаете return out.str().c_str(), вы возвращаете указатель на внутренние данные временного стека. Обратите внимание, что даже если строка не является переменной стека, c_str «предоставляется только для того, чтобы оставаться неизменным до следующего вызова непостоянной функции-члена строкового объекта».

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

0 голосов
/ 17 апреля 2010

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

Статическая локальная переменная std::ostringstream out не имеет смысла в этом случае, если только возвращаемая std :: string не является статической, что, как показывает ваше наблюдение, неверно.

0 голосов
/ 17 апреля 2010

В GetHandStateBrief переменная out не обязательно должна быть статической. Вам нужен явный static string для замены временного, который был создан в исходном вызове на out.str():

static std::string outStr;
std::ostringstream out;
... rest of function ...
outStr = out.str();
return outStr.c_str();
...