initialize struct contain references to structs

23,273

Solution 1

Give typeOuter an appropriate constructor:

struct typeOuter
{
  typeInner1 &one;
  typeInner2 &two;
  typeOuter(typeInner1 &a1, typeInner2 &a2) : one(a1), two(a2) {}
};



void fun(typeInner1 &arg1, typeInner2 &arg2) {
  typeOuter *ptr = new typeOuter(arg1, arg2);
  fun2(ptr);
}

Solution 2

Before C++11, you will need a constructor for your struct typeOuter, and initialize the member references in the initializer list:

typeOuter(typeInner1& i1, typeInner2& i2) : one(i1), two(i2) {}

With C++11 you also have the option of using an initializer list directly (without defining a constructor yourself):

typeOuter *ptr = new typeOuter { arg1, arg2 };

Solution 3

In C++ you can create a constructor for your struct. Structs are basically classes with public as default access modifier.

struct Example
{
    // struct fields..

    Example(); // initialize struct objects.
    ~Example(); // perform clean up if necessary.
};

Solution 4

Your problem is not with having references to structs, but with initializing references in general. References cannot be default-initialized, no matter whether they are references to a struct or to a built-in type.

int& x; // ERROR! Non-initialized reference to int
C& y; // ERROR! Non-initialized reference to a struct C
int z;
C w;
int& a = z; // OK: Initialized reference to int
C& b = w; // OK: Initialized reference to struct C

When your references are member variables of a struct, on the other hand (no matter what type they refer to), they must be bound as soon as your struct is constructed (just as regular references). Default-constructing your struct and then binding the references is not an option, because it is done in two steps, and references would be uninitialized after the first step.

Therefore, you have to provide a constructor for your struct and initialize your references there:

struct typeOuter {
  typeOuter(typeInner1& o, typeInner2& t) : one(o), two(t) { }
  typeInner1 &one;
  typeInner2 &two;
};    

Your fun() function would then look like this:

void fun(typeInner1 &arg1,typeInner2 &arg2){
    typeOuter *ptr = new typeOuter(arg1, arg2);
    fun2(ptr);
}

Solution 5

You could add a constructor, but you can also use aggregate initialization along with a factory function. This works in all versions of C++:

struct A
{
   int& i;
};

A make_a(int& i)
{
   A a = {i};
   return a;
}

int main()
{
   int i = 0;
   A* a = new A(make_a(i));
}
Share:
23,273
monkeyking
Author by

monkeyking

Updated on February 10, 2020

Comments

  • monkeyking
    monkeyking over 4 years

    Is it possible to have a struct containing references to structs. And how are these initialized? See short example below.

    Thanks

    typedef struct {
      int a;
    }typeInner1;
    
    
    typedef struct {
      int b;
    }typeInner2;
    
    
    typedef struct {
      typeInner1 &one;
      typeInner2 &two;
    }typeOuter;
    
    void fun2(typeOuter *p){
      p->one.a =2;
      p->two.b =3;
    }
    
    
    void fun(typeInner1 &arg1,typeInner2 &arg2){
      typeOuter *ptr = new typeOuter;//<-- how to write initializer
      fun2(ptr);
    }
    
    
    int main(){
      typeInner1 arg1;
      typeInner2 arg2;
      fun(arg1,arg2);
    
      //now arg1.a should be 2 and arg2.a=3
    }
    

    Ok thanks for all the input. I also had to modify the typedef of the typeOuter to make it work. Full working code below for other people finding this post.

    #include <cstdio>
    typedef struct {
      int a;
    }typeInner1;
    
    
    typedef struct {
      int b;
    }typeInner2;
    
    
    typedef struct typeOuter_t {
      typeInner1 &one;
      typeInner2 &two;
      typeOuter_t(typeInner1 &a1, typeInner2 &a2) : one(a1), two(a2) {}
    }typeOuter;
    
    void fun2(typeOuter *p){
      p->one.a =2;
      p->two.b =3;
    }
    
    
    void fun(typeInner1 &arg1,typeInner2 &arg2){
      typeOuter *ptr = new typeOuter(arg1,arg2);
      fun2(ptr);
    }
    
    
    int main(){
      typeInner1 arg1;
      typeInner2 arg2;
      fun(arg1,arg2);
    
      //now arg1.a shoule be 1 and arg2.a=3
      fprintf(stderr,"arg1=%d arg2=%d\n",arg1.a,arg2.b);
    }