0

I am seeing this unexpected output value with the following code while using a base class's reference as a variable inside another class. Can someone please help me to understand this?

#include <iostream>

class base {
public:
    explicit base(int val) : myVar(val) {
        std::cout << "base class constructor" << std::endl;
    }
    ~base() {
        std::cout << "base class destructor" << std::endl;
    }
    int getVal() { return myVar;}
private:
    int &myVar;
};

class someClass {
public:
    base &helloBase;
    someClass(base &obj) : helloBase(obj) {
        std::cout << "someClass constructor. "
                  << "value is : "
                  << helloBase.getVal()
                  << std::endl;
    }
    someClass(const someClass&) = delete;
    someClass(const someClass&&) = delete;
    someClass& operator=(someClass const &) = delete;
    someClass& operator=(someClass const &&) = delete;
    ~someClass() {
        std::cout << "someClass destructor" << std::endl;
    }
};

int main() {
    base newBase(10);
    std::cout << "Hello trial from base : " << newBase.getVal() <<  std::endl;
    someClass newSome(newBase);
    std::cout << "Hello trial from base again after new class obj creation : " << newBase.getVal() <<  std::endl;
    std::cout << "Hello trial from new class : " << newSome.helloBase.getVal() <<  std::endl;
    return 0;
}

and the output is as follows

base class constructor
Hello trial from base : 10
someClass constructor. value is : 32767
Hello trial from base again after new class obj creation : 32767
Hello trial from new class : 32767
someClass destructor
base class destructor
  • I'm not sure how you initialize the base with a reference to a temporary. – tadman Jul 25 '22 at 07:18
  • 1
    You are ignoring the **warning: binding reference member 'myVar' to stack allocated parameter 'val'**. – 273K Jul 25 '22 at 07:19
  • am not seeing any warning while building anandkrishnr@buildcontainer:~/anand$ g++ class-ref-trial.cc --std=c++11 -Wall -Werror -W anandkrishnr@buildcontainer:~/anand$ anandkrishnr@buildcontainer:~/anand$ – meetanandkr Jul 25 '22 at 07:24
  • 1
    `base` is storing a reference to the argument `val`. Accessing that reference after the constructor has returned is undefined. It's just bad luck that any of your code does what you expect. – molbdnilo Jul 25 '22 at 07:25
  • 1
    You are making `myVar` reference the constructor parameter `val`, which no longer exists after the constructor exits. – john Jul 25 '22 at 07:25
  • @meetanandkr [Unfortunately it seems GCC doesn't figure this out, but Clang does](https://godbolt.org/z/bYWETTjEd). Lesson of today: Always try building with different compilers. :) – Some programmer dude Jul 25 '22 at 07:27

1 Answers1

2

The problem is in base where your member variable myVar is a reference.

And the constructor then make it reference the local argument variable val.

Change myVar to be a value instead of a reference:

int myVal;  // Not a reference
Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • That works. The previous code with reference variable falls to "undefined behaviour" case right ? – meetanandkr Jul 25 '22 at 07:32
  • @meetanandkr Yes that's right, since the life-time of the `val` argument is much shorter than the reference, all uses of the reference after `val` disappears will lead to UB. – Some programmer dude Jul 25 '22 at 07:52