Мой коллега сегодня обнаружили очень тонкую ошибку в коде, который в основном пошли как это:Почему строка поддерживает `operator = (char)`?
double d = 65;
std::string s = "Hello world";
// .. somewhere later, accidentally assigning to s instead of a similarly
// named numerical variable.
s = d;
// s is now 'A'
Причина, по которой эта ошибка может произойти, я обнаружил, что std::basic_string<_Elem>
имеет оператор присваивания
_Myt& operator=(_Elem _Ch)
{ // assign 1 * _Ch
return (assign(1, _Ch));
}
Теперь компилятор действительно не жалуется (много, он излучает предупреждение о сужении конверсии, если уровень достаточно высок). Кажется, мы поймали эту ошибку достаточно рано, чтобы она не наносила большого ущерба, но мне было интересно, почему это разрешено. В конце концов, я не могу написать
std::string s = 65;
, потому что std::string
не имеет (п неявное) конструктор, который принимает char
. Не было бы безопаснее сделать это явное преобразование, которое заставляет вас писать
std::string s = string('A');
и что бы запретить присвоение одной _Elem
(char
).
Есть ли какие-либо основания для этого оператора присваивания? В то же коллеги правильно заметили,
double d;
char c = d;
допускается, тогда как
int* p = d;
не (для любого размера указателя) - по-видимому, потому что неявное преобразование от числа к указателю считается опасным. На самом деле, похоже, он даже превратился в C++ 11, который, насколько я видел, пытается быть довольно строгим и полезным в управлении типом данных.
Вот почему вы всегда устанавливаете предупреждения высоко! «как двойник, так и символ в четырех байтах» не уверены, что это значит. Они разных размеров. –
@NeilKirk Почему не установлен по умолчанию установленный уровень предупреждения? Никто не хочет, чтобы их компилятор был первым, кто похоронил код своих клиентов в море предупреждений обо всех своих плохих практиках? –
«это даже похоже на то, что он превратился в C++ 11» - потому что удаление его сломало бы 30-летний код устаревшего кода, так что не так легко сделать. –