why output is different when data member of class is changed to reference

时间:2018-03-23 00:15:30

标签: c++

Following program is giving the output as expected

#include <iostream>
#include <string>
using namespace std;
class test 
{
  string name; // non-referance
  public:
    test(string name1 = "default") :name (name1) {  cout << name << "  is constructed"<< endl;}
    ~test() { cout << name << " is destructed"<<endl;}
};
int main()
{
 test t1("Mike");
 test t2;
}

OUTPUT: As expected

Mike is constructed
default is constructed
default is destructed
Mike is destructed

When data member "name " is changed into reference variable, output is different( when both object are destructed, " name" values ("Mike" and "default") from output is gone , why?

class test 
{
  string &name; // **Make it reference**
  public:
    test(string name1 = "default") :name (name1) {  cout << name << "  is constructed"<< endl;}
    ~test() { cout << name << " is destructed"<<endl;}
};

OUTPUT: "Mike" and "default" are missing

Mike is constructed
default is constructed
is destructed
is destrcuted

1 个答案:

答案 0 :(得分:4)

The name1 parameter is local to the test constructor. It goes out of scope and is destroyed when the test constructor exits.

When name is not declared to be a reference, it is an actual string object whose lifetime is that of its containing test object. It copies data from name1 when initialized. As such, when name is used later in the test destructor, it is still a valid object with its own data, and you see the output you are expecting.

When name is declared to be a reference instead, it is not an object of its own, it is bound to the name1 object (it becomes an alias for name1), and is thus left dangling when name1 is destroyed. As such, when name is used later in the test destructor, it is no longer referring to a valid string object, and the code has undefined behavior.

The only way to make the latter case work correctly is to have name1 also be a reference to some external string that remains valid for the lifetime of the test object, eg:

#include <iostream>
#include <string>

using namespace std;

class test 
{
  string &name;
  public:
    test(string &name1) :name (name1) {  cout << name << "  is constructed" << endl; }
    ~test() { cout << name << " is destructed" << endl; }
};

int main()
{
  string name1 = "Mike";
  test t1(name1);

  string name2 = "default";
  test t2(name2);
}