Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does a member have to be initialized to take its address?

Tags:

Can I initialize a pointer to a data member before initializing the member? In other words, is this valid C++?

#include <string>  class Klass { public:     Klass()         : ptr_str{&str}         , str{}     {} private:     std::string *ptr_str;     std::string str; }; 

this question is similar to mine, but the order is correct there, and the answer says

I'd advise against coding like this in case someone changes the order of the members in your class.

Which seems to mean reversing the order would be illegal but I couldn't be sure.

like image 385
Ayxan Haqverdili Avatar asked May 10 '19 13:05

Ayxan Haqverdili


People also ask

Do pointers have to be initialized?

All pointers, when they are created, should be initialized to some value, even if it is only zero. A pointer whose value is zero is called a null pointer. Practice safe programming: Initialize your pointers!

How do you initialize a class member?

To initialize a class member variable, put the initialization code in a static initialization block, as the following section shows. To initialize an instance member variable, put the initialization code in a constructor.

How do you initialize a union?

An initializer for a structure is a brace-enclosed comma-separated list of values, and for a union, a brace-enclosed single value. The initializer is preceded by an equal sign ( = ).

Can we initialize the data member of structure?

Que: Can we initialize structure members within structure definition? No! We cannot initialize a structure members with its declaration, consider the given code (that is incorrect and compiler generates error).


1 Answers

Does a member have to be initialized to take its address?

No.

Can I initialize a pointer to a data member before initializing the member? In other words, is this valid C++?

Yes. Yes.

There is no restriction that operand of unary & need to be initialised. There is an example in the standard in specification of unary & operator:

int a; int* p1 = &a; 

Here, the value of a is indeterminate and it is OK to point to it.

What that example doesn't demonstrate is pointing to an object before its lifetime has begun, which is what happens in your example. Using a pointer to an object before and after its lifetime is explicitly allowed if the storage is occupied. Standard draft says:

[basic.life] Before the lifetime of an object has started but after the storage which the object will occupy has been allocated or, after the lifetime of an object has ended and before the storage which the object occupied is reused or released, any pointer that represents the address of the storage location where the object will be or was located may be used but only in limited ways ...

The rule goes on to list how the usage is restricted. You can get by with common sense. In short, you can treat it as you could treat a void*, except violating these restrictions is UB rather than ill-formed. Similar rule exists for references.

There are also restrictions on computing the address of non-static members specifically. Standard draft says:

[class.cdtor] ... To form a pointer to (or access the value of) a direct non-static member of an object obj, the construction of obj shall have started and its destruction shall not have completed, otherwise the computation of the pointer value (or accessing the member value) results in undefined behavior.

In the constructor of Klass, the construction of Klass has started and destruction hasn't completed, so the above rule is satisfied.


P.S. Your class is copyable, but the copy will have a pointer to the member of another instance. Consider whether that makes sense for your class. If not, you will need to implement custom copy and move constructors and assignment operators. A self-reference like this is a rare case where you may need custom definitions for those, but not a custom destructor, so it is an exception to the rule of five (or three).

P.P.S If your intention is to point to one of the members, and no object other than a member, then you might want to use a pointer to member instead of pointer to object.

like image 182
eerorika Avatar answered Jan 01 '23 21:01

eerorika