2012-08-09 10 views
12

I se dieron cuenta de la siguiente compila bien en GCC 4.7:¿Puedo asignar 0 a un shared_ptr? ¿Por qué?

#include <memory> 

int main() { 
    std::shared_ptr<int> p; 
    p = 0; 
} 

Sin embargo, no hay operador de asignación de int o desde int*, y no hay constructor implícito de cualquiera int o int* tampoco. Hay un constructor de int*, pero ese es explícito. Comprobé la implementación de la biblioteca estándar y el constructor es explícito y no hay operadores de asignación sospechosos a la vista.

¿El programa está realmente bien formado o GCC está jugando conmigo?

+4

'0' es el literal especial, se convierte en' nullptr_t' – Abyx

+2

@LucDanton porque g ++ es muy inteligente y convierte '42 ​​- 42' en' 0'. Lo mismo sucede (¿sucedió?) En Clang, IIRC, se mencionó en GN2012 – Abyx

+5

@Abyx No entendió el punto - '0' no tiene un tratamiento especial como literal en el idioma. –

Respuesta

16

La razón por la que esto funciona es este breve cita de la norma:

§4.10 [conv.ptr] p1

Una constante de puntero nulo es un expresión constante integral (5,19) prvalue de tipo entero que evalúa a cero o un prvalue de tipo std::nullptr_t. [...] Una constante de puntero nulo de tipo integral se puede convertir a un prvalue de tipo std::nullptr_t. [...]

Y el hecho de que std::shared_ptr tiene un constructor implícito de std::nullptr_t:

§20.7.2.2 [util.smartptr.shared] p1

constexpr shared_ptr(nullptr_t) : shared_ptr() { }

Esto también permite rarezas como esta:

#include <memory> 

void f(std::shared_ptr<int>){} 

int main(){ 
    f(42 - 42); 
} 

Live example.

+7

En cuanto a las rarezas como 42 - 42 que son constantes de puntero nulo, es probable que desaparezca, y [solo un literal 0 será una constante de puntero nulo válida] (http://www.open-std.org/jtc1/sc22/wg21/ docs/cwg_active.html # 903), en una versión futura de C++. – hvd

+0

@hvd: ¡Interesante, gracias por eso! – Xeo

0

Sólo puede asignar un puntero compartida a otra instancia de un puntero compartido. No es posible asignar el tipo compartido por shared_pointer. Aparentemente, este es el único sobrecarga para el operador:

shared_ptr& operator=(const shared_ptr& r);

Lo que está haciendo es la asignación de 0 (que en este caso es igual a NULL) para el puntero, no el valor del tipo. Tu tipo ni siquiera está inicializado en este punto del código.

+0

Eso realmente no aborda la pregunta: "¿por qué el compilador acepta esto sin quejarse?" – Flexo

Cuestiones relacionadas