Ita*_*iwa 6 c++ memory-address
正如我们所知,派生类public和protected成员的直接或间接基类在派生类中可用。
所以我有这个例子:
struct Foo{int x_ = 10;};
struct Bar : Foo{};
struct FooBar : Bar{
void f()const{
std::cout << &x_ << " : " << x_ << '\n';
std::cout << &Foo::x_ << " : " << Foo::x_ << '\n';
std::cout << &Bar::x_ << " : " << Bar::x_ << '\n';
std::cout << &FooBar::x_ << " : " << FooBar::x_ << '\n';
}
};
int main(){
FooBar fb{};
fb.f();
}
Run Code Online (Sandbox Code Playgroud)
当我编译并运行程序时,我得到输出:
0x7ffc2f7ca878 : 10
1 : 10
1 : 10
1 : 10
Run Code Online (Sandbox Code Playgroud)
那么为什么A::x_通过完全限定名称访问成员数据的地址会产生“无效”地址?但是直接访问它(不合格的查找)是可以的。
我的程序是否处于未定义行为?
我已经使用 GCC 和 CLANG 编译了我的程序。
首先,很可能您不打算&在每个std::cout语句中重复该运算符,因此我删除了每个重复的实例,以打印成员的值而不是其地址。
现在看这个:
#include <iostream>
struct Foo{int x_ = 10;};
struct Bar : Foo{};
struct FooBar : Bar
{
void f()const
{
std::cout << &x_ << " : " << x_ << '\n';
std::cout << &(Foo::x_) << " : " << Foo::x_ << '\n';
std::cout << &(Bar::x_) << " : " << Bar::x_ << '\n';
std::cout << &(FooBar::x_) << " : " << FooBar::x_ << '\n';
}
};
int main(){
FooBar fb{};
fb.f();
}
Run Code Online (Sandbox Code Playgroud)
输出:
0x7fffe136c594:10
0x7fffe136c594:
10 0x7fffe136c594:10
0x7fffe136c594:10
一切都很好!我所做的更改是将表达式括Foo::x_在括号中。为什么?由于&Foo::x_ 使用了内置地址运算符,请参阅cppreference.com 中的成员访问运算符。它的值是一个指向数据成员的指针,这不是一个普通的指针,因为它需要绑定到一个对象才能返回一个地址。另请参阅类似的 stackoverflow 问题以获取更多说明。
编辑
您可能想知道为什么要std::cout显示1指向成员的指针。这是因为隐式转换为bool:
布尔转换
整型、浮点型、无作用域枚举、指针和成员指针类型的纯右值可以转换为 bool 类型的纯右值。
转换后的值当然是true,因为您的指针是有效的,并且只有nullptr(和 0)被转换为false。根据其他规则,true转换为 1。QED