获取静态成员的地址
Taking address of a static member C++ FAQ
这个 c++常见问题解答试图传达什么?
可以取静态成员的地址,当(仅当)它具有类外定义:
class AE {
// ...
public:
static const int c6 = 7;
static const int c7 = 31;
};
const int AE::c7; // definition
int f()
{
const int* p1 = &AE::c6; // error: c6 not an lvalue
const int* p2 = &AE::c7; // ok
// ...
}
但是这个可以编译!
您使用-O2
进行编译。编译器可以优化掉const int* p1 = &AE::c6;
赋值(因为它没有效果),因此它不需要在最终代码中使用AE::c6
的地址,这就是它编译的原因。
它给出一个没有优化的链接错误。
你也得到一个链接错误,如果你开始使用p1
(例如std::cout << p1 << p2 << std::endl;
)链接
FAQ中的评论很容易误导人;AE::c6
和AE::c7
为左值。如果没有AE::c7
的定义,有问题的代码违反了一个定义规则:
在实践中,如果链接器通常会生成一个错误编译器实际上需要对象的地址。在你的情况下,如果以后不使用表达式可能被求值,除非它是未求值的操作数或其子表达式。一个变量谁的名字显示为可能求值的表达式是除非它是满足要求的对象,否则不使用用于出现在常量表达式和左值到右值之间立即应用转换。[…)
[…]
每个程序都应该包含每个函数的一个定义非内联函数或变量,在其中不使用程序;不需要诊断。
p2
,则编译器将不需要因为优化将删除p1
的定义。更常见的情况是: std::vector<int> v;
v.push_back( AE::c6 );
由于std::vector<>::push_back
接受引用,所以没有立即左值到右值的转换,定义是必需的。实际上,std::vector<>::push_back
是一个模板函数(通常是内联的),这样编译器就可以看到它的实现,并将值向下传播到函数中到左值到右值转换的地方发生,则代码将编译并正常工作。但它仍然是正式未定义行为
相关文章:
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- 如何在C++中使用非静态成员函数作为回调函数
- (C++)为什么静态成员可以在初始化之前使用
- 类的全局对象和静态成员
- 在作为静态成员包含在另一个类中的类的构造函数中使用 cout
- 模板化类中静态成员的延迟初始化
- 使用静态成员声明类时遇到问题
- C++:是否可以使用非静态成员变量模板?
- 静态成员函数使用相同的名称时出现模板类型名称错误
- 如何在复杂继承中访问静态成员变量
- 在 nullptr 上调用无状态类的非静态成员函数是否合法?
- 如何在友元函数中使用静态成员而不添加前缀 [类名]::
- C++构造函数和静态成员
- C++ - 非静态 void* 成员,指向具有相同地址但不同值的不同对象的另一个非静态成员
- 为什么有一个额外的 & 将非静态成员函数的地址传递给 C++ 中的线程?
- 错误:ISO C 禁止采用不合格或括号的非静态成员函数的地址,以形成指向成员函数的指针
- 为什么不允许非静态成员的地址作为模板非类型参数
- 类中静态成员的地址
- 获取静态成员的地址
- 如何获取在QtConcurrent中使用的非静态成员函数的地址