指向成员的指针混淆
Pointer-to-member confusion
我正在尝试了解此程序中抛出的错误的一致性:
#include <iostream>
class A{
public:
void test();
int x = 10;
};
void A::test(){
std::cout << x << std::endl; //(1)
std::cout << A::x << std::endl; //(2)
int* p = &x;
//int* q = &A::x; //error: cannot convert 'int A::*' to 'int*' in initialization| //(3)
}
int main(){
const int A::* a = &A::x; //(4)
A b;
b.test();
}
输出为10 10
。我标注了程序的4点,但是(3)是我最关心的:
x
通常从成员函数内部获取。
使用范围运算符获取对象的 x
并且对象 x
的左值是 returned.
- 给定
A::x
return 在 (2) 中编辑了一个 int
左值,为什么 &A::x
return 不是 int*
而是returns int A::*
?范围运算符甚至优先于 &
运算符,因此 A::x
应该首先是 运行,returning 一个 int
左值,然后再获取地址。也就是说,这肯定与 &(A::x)
相同吗? (顺便说一下,添加括号确实有效)。
- 当然这里有点不同,作用域运算符引用 class 成员但没有引用对象。
那么为什么 A::x
不是 return 对象的地址 x
而是 return 成员的地址,忽略 [=26] 的优先级=] 在 &
?
之前
基本上,只是选择语法 &A::x
(没有变化)来表示 pointer-to-member。
如果你写,例如,&(A::x)
,你会得到你期望的普通指针。
有关 pointers-to-members 的更多信息,包括关于此非常 属性 的注释,请参见 here。
C++ 标准没有明确指定运算符优先级;可以从语法规则中隐式地推断出运算符优先级,但这种方法无法理解像这样的特殊情况,它不适合传统的运算符优先级模型。
[expr.unary.op]/3:
The result of the unary &
operator is a pointer to its operand. The operand shall be an lvalue or a qualified-id. If the operand is a
qualified-id naming a non-static or variant member m
of some class C
with type T
, the result has type 'pointer to member of class C
of type
T
' and is a prvalue designating C::m
. Otherwise, if the type of the expression is T
, the result has type 'pointer to T
' and is a prvalue that is the address of the designated object or a pointer to the designated function.
/4:
A pointer to member is only formed when an explicit &
is used and its operand is a qualified-id not enclosed in parentheses. [ Note:
that is, the expression &(qualified-id)
, where the qualified-id is enclosed in parentheses, does not form an expression of type 'pointer to member'.
[expr.prim.general]/9:
A nested-name-specifier that denotes a class, optionally followed by the keyword template
, and then followed by the name of a member of either that class or one of its base classes, is a qualified-id.
如果 x
是 non-union 的 non-static 成员,则 &A::x
形式的表达式的类型为 "pointer to member x
of class A
" =] class A
,运算符优先级对此没有影响。
我正在尝试了解此程序中抛出的错误的一致性:
#include <iostream>
class A{
public:
void test();
int x = 10;
};
void A::test(){
std::cout << x << std::endl; //(1)
std::cout << A::x << std::endl; //(2)
int* p = &x;
//int* q = &A::x; //error: cannot convert 'int A::*' to 'int*' in initialization| //(3)
}
int main(){
const int A::* a = &A::x; //(4)
A b;
b.test();
}
输出为10 10
。我标注了程序的4点,但是(3)是我最关心的:
x
通常从成员函数内部获取。
使用范围运算符获取对象的 x
并且对象x
的左值是 returned.- 给定
A::x
return 在 (2) 中编辑了一个int
左值,为什么&A::x
return 不是int*
而是returnsint A::*
?范围运算符甚至优先于&
运算符,因此A::x
应该首先是 运行,returning 一个int
左值,然后再获取地址。也就是说,这肯定与&(A::x)
相同吗? (顺便说一下,添加括号确实有效)。 - 当然这里有点不同,作用域运算符引用 class 成员但没有引用对象。
那么为什么 A::x
不是 return 对象的地址 x
而是 return 成员的地址,忽略 [=26] 的优先级=] 在 &
?
基本上,只是选择语法 &A::x
(没有变化)来表示 pointer-to-member。
如果你写,例如,&(A::x)
,你会得到你期望的普通指针。
有关 pointers-to-members 的更多信息,包括关于此非常 属性 的注释,请参见 here。
C++ 标准没有明确指定运算符优先级;可以从语法规则中隐式地推断出运算符优先级,但这种方法无法理解像这样的特殊情况,它不适合传统的运算符优先级模型。
[expr.unary.op]/3:
The result of the unary
&
operator is a pointer to its operand. The operand shall be an lvalue or a qualified-id. If the operand is a qualified-id naming a non-static or variant memberm
of some classC
with typeT
, the result has type 'pointer to member of classC
of typeT
' and is a prvalue designatingC::m
. Otherwise, if the type of the expression isT
, the result has type 'pointer toT
' and is a prvalue that is the address of the designated object or a pointer to the designated function.
/4:
A pointer to member is only formed when an explicit
&
is used and its operand is a qualified-id not enclosed in parentheses. [ Note: that is, the expression&(qualified-id)
, where the qualified-id is enclosed in parentheses, does not form an expression of type 'pointer to member'.
[expr.prim.general]/9:
A nested-name-specifier that denotes a class, optionally followed by the keyword
template
, and then followed by the name of a member of either that class or one of its base classes, is a qualified-id.
如果 x
是 non-union 的 non-static 成员,则 &A::x
形式的表达式的类型为 "pointer to member x
of class A
" =] class A
,运算符优先级对此没有影响。