Getting C ++ Static Member Address Frequently Asked Questions

What does this C ++ FAQ try to convey?

You can take the address of a static member if (and only if) has a definition outside the class :

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 // ... } 

However this one compiles!

+7
c ++
source share
2 answers

Commenting in the FAQ is often misleading; both AE::c6 and AE::c7 are lvalues. If the definition of AE::c7 missing, this code violates one rule of definition:

An expression is potentially evaluated if it is not an unvalued operand or its subexpression. A variable whose name is displayed as a potentially evaluated expression is odr-used if it is not an object that meets the requirements for displaying in a constant expression and lvalue-to-rvalue conversion is immediately applied. [...]

[...]

Each program must contain exactly one definition of each non-built-in function or variable, which is used as an odr program; no diagnostics required.

In practice, the linker usually generates an error if the compiler really needed an object address. In your case, if p2 not used later, then the compiler will not need an address, since optimization will remove the definition of p1 . An even more common case when this happens is things like the following:

 std::vector<int> v; v.push_back( AE::c6 ); 

Since std::vector<>::push_back takes a link, there is no immediate conversion to lvalue-to-rvalue, but a definition is required. In practice, std::vector<>::push_back is a template (usually built-in), so the compiler can see its implementation and extend the value down to the function to the place where the lvalue-to-rvalue conversion actually takes place and the code will compile and work. But it is still formally undefined.

+5
source share

You use -O2 to compile. The compiler can optimize the assignment const int* p1 = &AE::c6; (since it has no effect), and therefore it does not need the address AE::c6 in the final code, so it compiles.

It gives a linker error without optimization.

You will also get a linker error if you start using p1 (for example, std::cout << p1 << p2 << std::endl; ) Link

+9
source share

All Articles