¿Cómo se puede y cómo no se puede utilizar un puntero nulo en C ++?





Para algunos, esta pregunta banal ya les ha puesto los dientes al borde, pero tomamos 7 ejemplos e intentamos explicar su comportamiento usando el estándar:



struct A {
    int data_mem;
    void non_static_mem_fn() {}
    static void static_mem_fn() {}
};

void foo(int) {}

A* p{nullptr};

/*1*/ *p;
/*2*/ foo((*p, 5));                     
/*3*/ A a{*p};
/*4*/ p->data_mem;
/*5*/ int b{p->data_mem};
/*6*/ p->non_static_mem_fn();
/*7*/ p->static_mem_fn();


Un detalle obvio pero importante: p , inicializado con un puntero nulo, no puede apuntar a un objeto de tipo A, porque su valor es diferente del valor de cualquier puntero a un objeto de tipo A conv.ptr # 1 .



Disclaimer: . dev.to, .



1



struct A {
    int data_mem;
    void non_static_mem_fn() {}
    static void static_mem_fn() {}
};

void foo(int) {}

A* p{nullptr};




*p;


(expression statement, stmt.expr#1), *p , , , . * expr.unary.op#1 , (indirection), l-, , . , , . .



, basic.stc#4, , (indirection through an invalid pointer value) . , , basic.compound#3.4, , — .



dcl.ref#5, , «the only way to create such a reference would be to bind it to the “object” obtained by indirection through a null pointer, which causes undefined behavior», .. — «», , . , «» (to bind), , , dcl.ref#5.



, , Core Working Group . , CWG ( drafting), , l- r-. « CWG» , , , 7. CWG.



. (N2176, 6.5.3.2 104), , , .



2



struct A {
    int data_mem;
    void non_static_mem_fn() {}
    static void static_mem_fn() {}
};

void foo(int) {}

A* p{nullptr};




foo((*p, 5));  


foo, , «». , , , , 1 (expr.comma#1). , .



3



struct A {
    int data_mem;
    void non_static_mem_fn() {}
    static void static_mem_fn() {}
};

void foo(int) {}

A* p{nullptr};




A a{*p};


a , , , const A& , (dcl.ref#5). .



4



struct A {
    int data_mem;
    void non_static_mem_fn() {}
    static void static_mem_fn() {}
};

void foo(int) {}

A* p{nullptr};




p->data_mem;


(*(p)).data_mem expr.ref#2, (designate) , (expr.ref#6.2). 1 , , , basic.lookup.qual#1, , to refer to designate , expr.ref. , , (. ).



5



struct A {
    int data_mem;
    void non_static_mem_fn() {}
    static void static_mem_fn() {}
};

void foo(int) {}

A* p{nullptr};




int b{p->data_mem};


, int. pr-, (basic.lval#1.2). int, (conv.lval#3.4), , basic.lval#11 .



6



struct A {
    int data_mem;
    void non_static_mem_fn() {}
    static void static_mem_fn() {}
};

void foo(int) {}

A* p{nullptr};




p->non_static_mem_fn();


class.mfct.non-static#1 , - , ( ), - . «» — «may be» /, . , .



7



struct A {
    int data_mem;
    void non_static_mem_fn() {}
    static void static_mem_fn() {}
};

void foo(int) {}

A* p{nullptr};




p->static_mem_fn();


1, Core Working Group . , 59, -> , .



constexpr



(expr.const#5), . , . , constexpr , , GCC, MSVC : godbolt



:



#





GCC 10.1

Clang 10

MSVC 19.24

1

*p;

+

+

+

+

2

foo((*p, 5));

+

+

+

+

3

A a{*p};

4

p->data_mem;

+

+

5

int b{p->data_mem};

6

p->non_static_mem_fn();

+

+

7

p->static_mem_fn();

+

+

+

+



6 4. , 1.



¡Gracias por quedarte con nosotros hasta el final para seguir las aventuras del puntero nulo en C ++! :-) Normalmente compartimos en Habré fragmentos de código de proyectos reales para el desarrollo de software embebido para electrónica, pero esta vez estábamos interesados ​​en cuestiones puramente "filosóficas", por lo que los ejemplos son sintéticos.



Si comparte nuestro amor por la controversia en C ++, comparta sus "dolorosas" en los comentarios. 




All Articles