
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.