resueltos - Diferencia entre los métodos de construcción de objetos C++
objetos en c++ (2)
Con C++ 14
o C++17
o C++11
, este comportamiento indefinido resulta en un error de compilación tanto en clang5.0
como en gcc7.2
.
#include<string>
std::string S(''/0'');
error: no hay función coincidente para la llamada a ''std :: __ cxx11 :: basic_string :: basic_string (char)'' std :: string S (''/ 0''); ^
La UB se corrige (para dar un error de compilación) en las versiones recientes del compilador.
Las diferentes sintaxis de construcción en C ++ siempre me han confundido un poco. En otra pregunta , se sugirió intentar inicializar una cadena como tal
std::string foo{ ''/0'' };
Esto funciona y produce el resultado deseado: una cadena de longitud 1 que contiene solo el carácter nulo. Al probar el código, accidentalmente escribí
std::string foo(''/0'');
Esto compila bien (sin advertencias incluso con -Wall
), pero termina en tiempo de ejecución con
terminate called after throwing an instance of ''std::logic_error''
what(): basic_string::_M_construct null not valid
Aborted (core dumped)
Ahora, por lo que puedo decir, no hay un constructor para std::string
que tome un solo carácter como argumento, y esta hipótesis se confirma aún más cuando intento pasar el carácter indirectamente.
char b = ''/0'';
std::string a(b);
Esto produce un error de compilación largo y agradable. Como hace esto
std::string a(''z'');
Así que mi pregunta es: qué permite std::string a(''/0'');
para compilar, y qué lo hace diferente de std::string a{ ''/0'' };
?
Nota al pie: Compilar usando g++
en Ubuntu. Esto no me parece un error de compilación, pero por si acaso ...
El carácter ''/0''
se puede convertir implícitamente a un valor entero de 0
lo que representa una constante de puntero nula definida por la implementación . Esta:
std::string foo(''/0'');
llama a una sobrecarga del constructor que acepta un puntero de tipo const char*
como parámetro y da como resultado un comportamiento indefinido. Es equivalente a pasar 0
o NULL
:
std::string foo(0); // UB
std::string bar(NULL); // UB
La referencia para las sobrecargas de constructores 4 y 5 dice:
El comportamiento no está definido si s ... incluido el caso cuando s es un puntero nulo .
La segunda afirmación:
std::string foo{''/0''}; // OK
llama a un constructor que acepta std::initializer_list<char>
como parámetro y no causa UB.
En su lugar, puede llamar al número de conteo de caracteres de la sobrecarga del constructor:
std::string s(1, ''/0'');