(为什么)我们可以在初始化中将非静态类成员分配给静态变量吗?
(Why) can we assign non-static class members to static variables in initialization?
在更大的代码库中,我遇到了这样的代码(参见godbolt(:
struct Foo {};
struct Base {
Foo* a;
};
struct Bar : public Base {
static Foo* Bar::*mybar[];
};
Foo* Bar::Bar::*mybar[] = {
&Base::a
};
老实说,我很困惑。这看起来像是用非静态成员变量Base
初始化Bar
中的Foo
指针的静态数组。没有对象怎么可能?
(免责声明:这在实际有效的生产代码中找到 - 希望不依赖 UB?
另外,如果我像这里一样删除限定名称查找是否有任何问题?我想重构代码并使其更具可读性。所有这些Bar::
似乎都是多余的,但由于我对代码不太满意,我宁愿先了解其中的含义。
与普通指针不同,类成员指针可以作为类的偏移量,它们告诉您它们指向对象的哪个成员。 因此,在您的代码中,mybar
是一个类成员指针数组。 当你这样做时
Foo *Bar::Bar::*mybar[] = {
&Base::a
};
使用指向Base
的a
成员的指针初始化数组。 这实际上并不指向a
,它只是告诉编译器,如果您使用对象访问它,要返回对象的哪个成员。 那看起来像
Base foo; // now we have an actual object
foo.*mybar[0]; // access the `a` member of `foo` by using the "offset"
没有对象怎么可能?
可以在没有对象的情况下创建指向成员变量的指针。指针可用于仅在存在对象的情况下取消引用实际成员。
更简单的例子:
struct Foo { int m; int n};
using MemberPtr = int Foo::*;
MemberPtr p1 = &Foo::m; // Instance of Foo is not needed.
MemberPtr p2 = &Foo::n; // Instance of Foo is not needed.
*p1 = 10; // Not allowed.
*p2 = 20; // Not allowed.
Foo a;
a.*p1 = 10; // Changes a.m
a.*p2 = 20; // Changes a.n
Foo b;
b.*p1 = 30; // Changes b.m
b.*p2 = 40; // Changes b.n
请注意,您可以使用指向成员变量的同一指针更改类的两个实例的成员值。
首先,Bar::mybar
是指向成员的指针数组。这些不是实际的指针。它们更像是对对象偏移量的抽象。它们允许间接访问成员。给定一个Base
对象(或从它派生的对象(,我们可以调用它们,如下所示
aBar.*mybar[0] // This resolve to a Foo* inside aBar
另一件需要注意的事情是,在您的示例中,命名空间范围内的对象不是Bar::mybar
的定义。这是一个不相关的数组。正确的定义是
Foo* Bar::* Bar::mybar[] = {
&Base::a
};
这是因为您的定义是错误的,因此删除某些限定名称不起作用。当您删除它时,您只剩下
static Foo *mybar[];
Foo Bar::*mybar[] = {
&Base::a
};
声明的类型与"定义"不匹配。但是你没有错误,因为这些实际上是不同的对象。
在正确的定义中,每个Bar::
限定符都是必需的,并且具有不同的目的。一个用于创建正确的类型(指向Bar
成员的指针(,另一个用于指定正在定义的Bar
的静态成员,并且在每个静态类成员定义中都是必需的。
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- 我有一个对象,它将在整个程序的持续时间内实例化,但一个类成员不会,我应该动态分配它吗?
- 在对象指针上调用 Delete 是否会递归删除其动态分配的成员
- C++类成员:堆栈与堆分配
- 为什么在分配给成员变量之前获取unique_ptr的返回是一个问题?
- (为什么)我们可以在初始化中将非静态类成员分配给静态变量吗?
- 在成员初始值设定项列表中分配unique_ptr
- 对象分配-成员函数的使用无效错误
- 如何确定对象是否已分配成员
- 我可以分配成员访问操作员的返回值吗?
- lambda表达式分配成员函数指针
- 如何在C++中从命令行参数分配成员变量
- 为什么分配成员会引发 NullReferenceException
- 错误:在只读对象中分配成员
- 在只读对象中分配成员 '
- 分配成员变量时出现分段错误
- 具有动态分配成员的结构体的向量
- 按值分配成员对象:我的假设是否正确
- 创建std::shared_ptr来分配成员变量时内存泄漏
- 处理包含动态分配成员的对象向量