.c_str() странность? Данные изменяются без рифмы или причины?

У меня есть эта простая функция:

const wchar_t *StringManager::GetWCharTStar(int stringId)
{
    std::wstring originalString = StringManager::GetString(stringId);
    const wchar_t *retStr = originalString.c_str();
    return retStr;
}

Во второй строке этой функции у меня есть правильный wchar_t*. Однако когда я возвращаюсь, данные переключаются на ненужные данные. Между ними нет функций. Что дает?!

5 ответов

Решение

originalString размещается в стеке. Метод.c_str() просто возвращает указатель на некоторую непрерывную внутреннюю память объекта wstring. Когда функция возвращается, originalString выходит из области видимости и уничтожается, поэтому возвращаемое вами значение указателя указывает на удаленную память.

Если вам нужно сделать это, вы должны сделать копию данных в памяти, которую вы выделяете с помощью ne w или malloc(), а затем вызывающая сторона должна удалить / освободить () эту память.

Вы возвращаете указатель на временный. Когда originalString выходит из области видимости, данные, на которые указывает указатель, будут удалены.

std::wstring originalString; это локальная переменная внутри тела вашего GetWCharTStar функция.

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

Следующий код может в конечном итоге работать:

const wchar_t *StringManager::GetWCharTStar(int stringId)
{
    const std::wstring& originalString = StringManager::GetString(stringId);
    const wchar_t *retStr = originalString.c_str();
    return retStr;
}

Предоставлена StringManager::GetString() возвращает ссылку:

const std::wstring& StringManager::GetString(int stringId);

Тем не менее, это все еще рискованно, так как предполагает, что строки управляются вашим StringManager класс никогда не будет перемещен в память. Например, если StringManager реализуется с помощью std::vector затем, как только вектор должен расшириться, его предыдущее содержимое копируется в другое место в большем блоке памяти, и вы в конечном итоге удерживаете ссылку на объект, которого больше нет.

Другими словами, избегайте возврата дескрипторов внутренних данных.

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

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

Другие вопросы по тегам