Устаревшее преобразование из строки const.на wchar_t * - PullRequest
5 голосов
/ 23 сентября 2010

Здравствуйте, у меня есть класс насоса, который требует использования переменной-члена, которая является указателем на массив wchar_t, содержащий адрес порта, т. Е. "Com9".

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

pump::pump(){
   this->portNumber = L"com9";}

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

Я попытался создать массив и затем установить переменную-член следующим образом:

pump::pump(){
   wchar_t port[] = L"com9";
   this->portNumber = port;}

Но по какой-то причине это делает мой номер порта номером «F».

Очевидно, еще одна концептуальная проблема с моей стороны.

Спасибо за помощь в моих нубистских вопросах.

EDIT:

В качестве запроса определение portNumber было:

    class pump
{
private:
   wchar_t* portNumber;
}

Благодаря ответам теперь оно изменено на:

    class pump
{
private:
   const wchar_t* portNumber;
}

Ответы [ 3 ]

13 голосов
/ 23 сентября 2010

Если portNumber является wchar_t*, это должно быть const wchar_t*.

Строковые литералы являются неизменяемыми, поэтому элементы const. Существует устаревшее преобразование из строкового литерала в неконстантный указатель, но это опасно. Внесите изменения, чтобы сохранить безопасность типов и не использовать небезопасное преобразование.

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

Наконец, используйте список инициализации:

pump::pump() :
portNumber(L"com9")
{}

Список инициализации должен инициализироваться, конструктор должен закончить конструкцию. (Кроме того, this-> уродлив почти для всех людей на C ++; это нехорошо и избыточно.)

2 голосов
/ 23 сентября 2010

Используйте const wchar_t*, чтобы указать на литерал.

Причина, по которой преобразование существует, состоит в том, что в ранних версиях C было допустимо назначать строковый литерал неконстантному указателю [*]. Причина, по которой он устарел, заключается в том, что модифицировать литерал недопустимо, и рискованно использовать неконстантный указатель для ссылки на то, что нельзя изменять.

[*] C изначально не имел const. Когда был добавлен const, очевидно, что он должен применяться к строковым литералам, но там уже был код, написанный до того, как существовал const, который сломался бы, если вдруг вам пришлось бы посыпать const везде. Мы все еще платим сегодня за это критическое изменение языка. Поскольку вы используете C ++, это не было даже серьезным изменением в этом языке.

1 голос
/ 23 сентября 2010

Очевидно, portNumber является wchar_t * (неконстантным), правильно?Если так:

  • первый неверен, потому что строковые литералы доступны только для чтения (они являются константными указателями на массив char , обычно , хранящийся в таблице строкисполняемого файла, который отображается в памяти где-то, часто на странице только для чтения).Уродливое, неявное преобразование в неконстантные char s / wchar_t s было одобрено IIRC для достижения совместимости со старым кодом, написанным, когда const даже не существовало;к сожалению, он позволил многим дебилам, которые не знают, что означает const правильность , избежать написания кода, который запрашивает неконстантные указатели, даже когда константные указатели будут правильным выбором.

  • Второй вариант неверен, потому что вы portNumber указываете на переменную, расположенную в стеке, которая удаляется при возврате конструктора.После возврата конструктора указатель, хранящийся в portNumber, указывает на случайный мусор.

Правильный подход - объявить portNumber как const wchar_t *, если его не нужномодифицирована.Если вместо этого его нужно изменить в течение жизни класса, обычно лучший способ - вообще избежать строк в стиле C и просто добавить std::wstring, который позаботится овся бухгалтерия, связанная со строкой.

...