С++ MFC отсутствует переменная const char *

Итак, у меня есть этот простой код внутри метода нажатия кнопки:

std::stringstream ss;
unsigned counter = 0;
while(true)
{
    ss.clear();
    ss << DEFAULT_USER_CONFIG_NAME << " " << ++counter;
    const char* name = ss.str().c_str();
    MessageBox(name);

    /* ... while break condition */
}

Проблема в том, что окно сообщения пусто. Но он работает правильно, когда я передаю текст напрямую:

MessageBox(ss.str().c_str()); // that shows text just fine

Что я обнаружил с помощью отладчика, так это то, что локальная переменная «имя» не создается (по крайней мере, она не отображается в отладчике). Любая подсказка, почему он работает, когда передается напрямую, а в противном случае - нет? Также, когда я передал «имя» CString, оно вернуло true при проверке IsEmpty().


person Arrekin    schedule 12.09.2016    source источник
comment
Все согласно стандарту. Проблема с первой версией заключается в том, что ss.str() уничтожается до вызова MessageBox(name). У вас есть какие-либо вопросы?   -  person LogicStuff    schedule 12.09.2016


Ответы (1)


Выражение ss.str() создает временный объект std::string. Таким образом, сохранение результата c_str() указывает на временную память, которая быстро превращается в оборванный указатель. Как только оператор полного выражения

const char* name = ss.str().c_str();
//                                 ^ this is where the temporary ss.str() gets destroyed.

оценивается, временное уничтожается.

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

MessageBox(ss.str().c_str());
//                          ^ this is where the temporary ss.str() gets destroyed.

Далее показана последовательность событий. Давайте просто определим несколько классов-заполнителей и функций:

void messagebox(const char*) {
    cout << "messagebox()" << endl;
}

struct tmp {
    tmp(const char* content) : content(content) { cout << "tmp c'tor" << endl; }
    ~tmp() { cout << "tmp d'tor" << endl; }
    const char* c_str() { return content.c_str(); }
private:
    string content;
};

struct ss {
    tmp str() { return tmp("test"); }
};

После этого ваша первая версия

ss s;
const char* name = s.str().c_str();
messagebox(name);

производит следующий вывод:

tmp c'tor
tmp d'tor
messagebox()

При этом вторая версия

ss s;
messagebox(s.str().c_str());

изменяет последовательность в выводе:

tmp c'tor
messagebox()
tmp d'tor

(Текущий пример кода)

person IInspectable    schedule 12.09.2016
comment
Спасибо за ваш ответ. Есть идеи, почему отладчик вообще не показывает имя переменной? [Визуальная студия 2010] - person Arrekin; 14.09.2016
comment
@Arrekin: в первом фрагменте кода name должно отображаться как на вкладках Locals, так и на вкладках Autos. Если не показывает, то не знаю почему. В отладочной сборке он должен указывать на строку с содержимым 0xCD, помечающую освобожденную память. Если вам нужно проверить переменные, которые не отображаются автоматически, вы всегда можете добавить смотреть. - person IInspectable; 14.09.2016