How to Initialize the Reference Member Variable of a Class

Initializing a reference variable in a class constructor

Since data is a reference, you must initialize it at constructor initializer:

AVLNode(T & newData): data(newData) {

}

You may find this post useful: reference member variable must be initialized at constructor initialization list. You may also need to understand the difference between initialization and assignment when you write a class's constructor.

Quoting from C++ Primer pp455:

Some members must be initialized in the constructor initializer. For such members, assigning to them in the constructor body doesn't work. Members of a class type that do not have default constructor and members that are const or reference types must be initialized in the constructor initializer regardless of type.

How to initialize a reference member variable inside a member function & access it inside other member functions - C++

I think this is the best you can do.

#include <iostream>
using namespace std;

class abc {
public:
int& var;
abc(int& temp) :
var(temp)
{}
void fun2 () {cout << abc::var << endl;}
};

int main() {
int y=9;
abc f(y);
f.fun2();
return 0;
}

A reference is a constant thing — it refers to the same integer for the entire lifespan of the object. That means you need to set it on construction.

How to initialize the reference member variable of a class?

That is because references can only be initialized in the initializer list. Use

Test (int &x) : t(x) {}

To explain: The reference can only be set once, the place where this happens is the initializer list. After that is done, you can not set the reference, but only assign values to the referenced instance. Your code means, you tried to assign something to a referenced instance but the reference was never initialized, hence it's not referencing any instance of int and you get the error.

Initialization of reference member requires a temporary variable

A reference must be initialised to refer to something; it can't refer to nothing, so you can't default-construct a class that contains one (unless, as others suggest, you define a global "null" value). You will need a constructor that is given the Div to refer to:

explicit A(Div &d) : divs(d) {}

If you want it to be able to be "null", then you need a pointer, not a reference.

Reference member variables as class members

Is there a name to describe this idiom?

In UML it is called aggregation. It differs from composition in that the member object is not owned by the referring class. In C++ you can implement aggregation in two different ways, through references or pointers.

I am assuming it is to prevent the possibly large overhead of copying a big complex object?

No, that would be a really bad reason to use this. The main reason for aggregation is that the contained object is not owned by the containing object and thus their lifetimes are not bound. In particular the referenced object lifetime must outlive the referring one. It might have been created much earlier and might live beyond the end of the lifetime of the container. Besides that, the state of the referenced object is not controlled by the class, but can change externally. If the reference is not const, then the class can change the state of an object that lives outside of it.

Is this generally good practice? Are there any pitfalls to this approach?

It is a design tool. In some cases it will be a good idea, in some it won't. The most common pitfall is that the lifetime of the object holding the reference must never exceed the lifetime of the referenced object. If the enclosing object uses the reference after the referenced object was destroyed, you will have undefined behavior. In general it is better to prefer composition to aggregation, but if you need it, it is as good a tool as any other.

Reference member variable initialization error with default constructor

why defining a default constructor throws compilation error?

It's not that you define a default constructor, it's that the default constructor's definition doesn't initialize i. You are required to initialize all member variables that are references, and your empty definition does not do that.

This is for the same reason that you are required to initialize reference variables:

void foo() {
int &i; // error: declaration of reference variable 'i' requires an initializer
}

why would the compiler allow declaration of default constructor(without definition)

Because the definition is the problem, not the declaration. For example, moving the ill-formed constructor definition outside of the class definition will yield the same error:

class SomeClass
{
public:
SomeClass();
int &i;
};

SomeClass::SomeClass() {} // error: constructor for 'SomeClass' must explicitly initialize the reference member 'i'

The only problem with both examples is that you're not initializing i.

Take note of the following examples, which will compile. Note that the constructor's declaration does not change, but the definition does initialize i.

int someGlobalInt;

class SomeClass
{
public:
SomeClass() : i(someGlobalInt) {}
int &i;
};

int someGlobalInt;

class SomeClass
{
public:
SomeClass();
int &i;
};

SomeClass::SomeClass() : i(someGlobalInt) {}

Initializing reference member variable with literal

Well clang produces the following warning for this code even without any flags (see it live):

warning: binding reference member 'a' to a temporary value [-Wdangling-field]
ABC():a(43) { }
^~

gcc on the other hand requires either -Wall or -Wextra.

and if we check out this reference initialization reference it says:

a temporary bound to a reference member in a constructor initializer list persists only until the constructor exits, not as long as the object exists.

This can be found in the draft C++ standard section 12.2 Temporary objects paragraph 5 which includes the following bullet

— A temporary bound to a reference member in a constructor’s ctor-initializer (12.6.2) persists until the constructor exits.

Initialize reference member in class C++

References are basically like pointers, but with two very important difference: a) they must be initialized when created (in order to minimize the possibility of having a dangling references in contrast to a dangling pointer), and b) cannot change the object they point to.

In your code, you have the needs that maybe can be covered by b), but not for a)(you say you'll get the value for _userBody "later", not in the time of building the object), so the you've only two possibilities left: use a simple object (which you can initialize by copying the new value) [not very good], or just use a pointer instead of a reference.

class SampleClass {
public:
SampleClass(bool mirror=false);
void updateFunction();
private:
BodyTrackeDevice _device;
BodyBlob * _userBody;
BodyMuscle _muscle;
bool _mirror;
};

SampleClass::SampleClass(bool mirror)
{
this->_mirror = mirror;
}

void SampleClass::updateFunction()
{
_userBody = &( device.getTrackedBody[ 0 ] );
}

Hope this helps.

How can I initialise a reference member in the default constructor?

You need to use the member initialization list:

struct foo
{
const int& ref;
foo() : ref(some_value()) { }
}

Make sure some_value() doesn't give you a temporary. It will only have its life extended until the end of the constructor:

A temporary bound to a reference member in a constructor’s ctor-initializer (12.6.2) persists until the constructor exits.

Initializing a reference member: reason for different syntax

It's because { myClassReference = reference; } is considered as an
assignment to something which is supposed to be already initialised.

The member initialisation list : member1{value1}, member2{value2}...
is intended to provide the initial value (nothing is supposed to
be valid before).

For the specific case of a reference, it's the same situation as

int i=4;
int &r=i; // the reference is initialised (alias for i)
r=5; // the reference itself is not changed but
// the referenced object (i) is assigned


Related Topics



Leave a reply



Submit