0

I am making a tree-based data structure where there is one immutable root and each node is assigned a parent that never changes. Each node requires a reference to the parent.

I decided to use references instead of pointers, and came up with the following attempt to check if a particular node is the root:

#include <cstdio>

class Obj {
public:
    Obj &parent;
    Obj(Obj &parent) : parent(parent) {}
    int hasparent();
};

int Obj::hasparent()
{
    return &parent != this;
}

int main()
{
    Obj base(base);
    Obj child(base);

    printf("base.hasparent = %d\n", base.hasparent());
    printf("child.hasparent = %d\n", child.hasparent());
    printf("child.parent.hasparent = %d\n", child.parent.hasparent());
}

I would like your critique. Is this correct? Being unfamiliar with C++, I am actually surprised that the compiler allowed me to pass a reference to an object that I didn't construct yet. Is this the right approach?

giusti
  • 3,156
  • 3
  • 29
  • 44
  • Why don't you just set the parent to `nullptr` instead of itself? – Patrick Roberts May 01 '18 at 19:31
  • @PatrickRoberts I dismissed that after reading that [references must point to valid objects](https://stackoverflow.com/questions/4364536/is-null-reference-possible). – giusti May 01 '18 at 19:36
  • only problem with this approach is that tree becomes statically defined, can't be relocated. – Swift - Friday Pie May 01 '18 at 19:36
  • I'm surprised that the compiler allows it, but it appears to work. You could also consider using `const` pointers. – Beta May 01 '18 at 19:37
  • 1
    @giusti Patrick may be proposing you make `parent` a `Obj*` instead of a `Obj &`. – François Andrieux May 01 '18 at 19:38
  • @Beta this is not against standard, so compiler can't forbid this. "&parent != this;" might be problem on some platforms where automatic relocation is possible, but those platforms themselves deviate from standard. – Swift - Friday Pie May 01 '18 at 19:39
  • 7
    Strictly speaking, there is nothing wrong here. Though using a refrence type as a data member makes your class unassignable and unmovable. – François Andrieux May 01 '18 at 19:40
  • 2
    [Why is initialization of a new variable by itself valid?](https://stackoverflow.com/questions/28152298/why-is-initialization-of-a-new-variable-by-itself-valid) – François Andrieux May 01 '18 at 19:42
  • @FrançoisAndrieux That's the approach I would take in C. But I'm studying C++ so I decided to see what I can do with references. – giusti May 01 '18 at 19:44
  • @FrançoisAndrieux I think, it's not the same case, because here we initialize reference. That's equal to initializing pointer with address of uninitialized variable. – Swift - Friday Pie May 01 '18 at 19:44
  • @giusti issue with references is that are immutable, once initialized. If your target is to create object which you can't change legally then it's valid point. – Swift - Friday Pie May 01 '18 at 19:45
  • 1
    @Swift That's mentioned in the accepted answer. It uses `void *p = &p;` as an example. – François Andrieux May 01 '18 at 19:45
  • @FrançoisAndrieux alright, I need more booze.. I can't do inception that deep right now – Swift - Friday Pie May 01 '18 at 19:46
  • @Swift Thanks for the remark. In this particular structure, once a node is created, the parent will never change. – giusti May 01 '18 at 19:48
  • I'd have the parent point to the child using a `std::shared_ptr`, and the child point to the parent using `std::weak_ptr`. – Eljay May 01 '18 at 19:55

1 Answers1

2

I don't see a problem with your code. If you want to hide the "weird looking initialization" of "Obj base (base)", then you could implement the default constructor to set the parent to the object itself:

Obj() : parent(*this) { }

Then you can simply initialize base like this:

Obj base;
tangoal
  • 724
  • 1
  • 9
  • 28