3

Is it safe to store reference/pointer on uninitialized data member?

Not use, but store at some moment of time.

I know that I have to use smart pointers. But for code simplicity I decide to give an example with owning raw pointers. Which is not very good in practice but I think good enough for example.

Here is the example of code:

struct Node {
    Node(Node*& node_ptr) : list_first_node_ptr{node_ptr} {}
    /* ... */
    Node*& list_first_node_ptr;
};

struct List {
    // Is this line - dangerous?
    List() : first_node_ptr{new Node{first_node_ptr}} {}
    /* ... */
    Node* first_node_ptr;

    ~List() {delete first_node_ptr;}
};

I initialize first_node_ptr with Node object, but pass in constructor of Node object still not uninitialized first_node_ptr.


One more question: is memory already allocated for first_node_ptr when I pass it, so will the reference address at Node constructor be valid?

I think that this example is about the same but simplified version. I'm right?

class Base {
 public:
    // var_ptr points to uninitialized va
    Base() : var_ptr{&var}, var{10} {}

    int* var_ptr;
    int var;
};

P.S. Why when I write (Node*)& instead of Node*& I get compilation errors about incomplete type?

P.P.S. Can the usage of smart pointers change the situation?

P.P.P.S. @JesperJuhl asked about use case. The idea is to create circular linked list where every Node has a reference on Head pointer to first sentinel Node. I get this idea from Herb Sutter in CppCon video 2016 43:00. In video he talked about unique pointers but I give example with raw pointers, it may be become a little bit confusing.

Gusev Slava
  • 2,136
  • 3
  • 21
  • 26

1 Answers1

1

Node::list_first_node_ptr is a reference. It doesn't care about the value of the referenced object, just that the referenced object itself actually exists. Since List::first_node_ptr is guaranteed to exist when Node::list_first_node_ptr is constructed, this is legal code.

To phrase it another way; a reference can never be null, but it can reference a pointer that is null.

It's worth noting, though, that List::first_node_ptr will not point to a valid object until Node has finished constructing. This means you can't dereference List::first_node_ptr or Node::list_first_node_ptr until the Node constructor has finished.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
Fibbs
  • 1,350
  • 1
  • 13
  • 23
  • Nitpicking: _you can reference a pointer which is null_ - the pointer has an indeterminate value initially. – Maxim Egorushkin Jun 21 '18 at 18:55
  • 1
    The one in his example does, I was just trying to keep the rephrasing simple to understand. Either way, dereferencing a null pointer or a pointer in an indeterminate state is undefined behaviour. – Fibbs Jun 21 '18 at 20:42