بالنسبة للبعض ، هذا السؤال العادي وضع الأسنان بالفعل على حافة الهاوية ، لكننا أخذنا 7 أمثلة وحاولنا شرح سلوكهم باستخدام المعيار:
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();
تفاصيل واضحة ولكنها مهمة: لا يمكن أن يشير p ، الذي تمت تهيئته بمؤشر فارغ ، إلى كائن من النوع A ، لأن قيمته تختلف عن قيمة أي مؤشر إلى كائن من النوع A conv.ptr # 1 .
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.
شكرًا لك على بقائك معنا حتى النهاية لمتابعة مغامرات المؤشر الفارغ في C ++! :-) عادة ما نشارك على Habré أجزاء من التعليمات البرمجية من مشاريع حقيقية لتطوير البرمجيات المدمجة للإلكترونيات ، لكن هذه المرة كنا مهتمين بالأسئلة "الفلسفية" البحتة ، لذا فإن الأمثلة تركيبية.
إذا كنت تشارك حبنا للجدل في C ++ ، فشارك معجبيك "المؤلمين" في التعليقات.