C++ 在初始化列表中初始化引用

C++ 在初始化列表中初始化引用,c++,C++,我被告知必须在初始化列表中初始化引用变量,但为什么这是错误的 class Foo { public: Foo():x(0) { y = 1; } private: int& x; int y; }; 因为0是临时对象?如果是,引用可以绑定到什么类型的对象?可以获取地址的对象 谢谢 0不是左值,而是右值。您无法修改它,但您正在尝试绑定到可以修改它的引用 如

我被告知必须在初始化列表中初始化引用变量,但为什么这是错误的

   class Foo
    {
    public: 
        Foo():x(0) {      
         y = 1;
        }
    private:
        int& x;
        int y;
    };
因为0是临时对象?如果是,引用可以绑定到什么类型的对象?可以获取地址的对象


谢谢

0不是左值,而是右值。您无法修改它,但您正在尝试绑定到可以修改它的引用

如果您将引用设置为const,它将按预期工作。考虑这一点:

int& x = 0;
x = 1; // wtf :(
这显然是不可能的。但是
常量&
可以绑定到临时值(右值):

请注意,临时设备的使用寿命在建造完成时结束。如果您对常量进行静态存储,您将是安全的:

class Foo
{
public:
    static const int Zero = 0;

    Foo() : x(Zero) // Zero has storage
    {
        y = 1;
    }
private:
    const int& x;
    int y;
};

长寿命引用必须绑定到
左值
。基本上,正如你雄辩地说的,一个有明确地址的对象。如果它们被绑定到一个临时文件,那么当引用仍在引用它并且结果未定义时,临时文件将被销毁

短期常量引用(局部函数变量和函数参数)可以绑定到临时变量。如果是,则保证在引用超出范围之前不会销毁临时文件

演示代码:

#include <iostream>

class Big {
 public:
   Big() : living_(true), i_(5) { // This initialization of i is strictly legal but
      void *me = this;            // the result is undefined.
      ::std::cerr << "Big constructor called for " << me << "\n";
   }
   ~Big() {
      void *me = this;
      living_ = false;
      ::std::cerr << "Big destructor called for " << me << "\n";
   }

   bool isLiving() const { return living_; }
   const int &getIref() const;
   const int *getIptr() const;

 private:
   ::std::string s_;
   bool living_;
   const int &i_;
   char stuff[50];
};

const int &Big::getIref() const
{
   return i_;
}

const int *Big::getIptr() const
{
   return &i_;
}

inline ::std::ostream &operator <<(::std::ostream &os, const Big &b)
{
   const void *thisb = &b;
   return os << "A " << (b.isLiving() ? "living" : "dead (you're lucky this didn't segfault or worse)")
             << " Big at " << thisb
             << " && b.getIref() == " << b.getIref()
             << " && *b.getIptr() == " << *b.getIptr();
}

class A {
 public:
   A() : big_(Big()) {}

   const Big &getBig() const { return big_; }

 private:
   const Big &big_;
};

int main(int argc, char *argv[])
{
   A a;
   const Big &b = Big();
   const int &i = 0;
   ::std::cerr << "a.getBig() == " << a.getBig() << "\n";
   ::std::cerr << "b == " << b << "\n";
   ::std::cerr << "i == " << i << "\n";
   return 0;
}

好吧,你永远不能改变它,0永远不能等于0以外的任何东西

试一试


或者,如果引用是常量,则可以执行此操作,因为0只能等于0

一旦构造函数完成,引用将无效:/不,当传入构造函数的int超出调用函数的作用域时,引用将无效。是的,编辑后的响应非常低。你应该说“我搞定了”而不是“你错了”(很抱歉,GMan,在我编辑之后,我再次查看了页面,但是你的评论不在那里。当我回来时,我看到了你的评论。但是,如果他声明成员变量
const
,那么他的构造函数中的具体示例仍然会失败。当临时0被销毁时会发生什么?如果它的地址被占用,并且该解除引用又如何enced?这个答案是错误的,并且没有回答OPs问题,我只是测试了一下。@Omnifarious:我不确定你的意思。它按预期工作;你也可以使用地址。@GMan,看看我发布的代码和程序运行的结果。引用最后被垃圾填满,如果你输入的值不是0,你就得不到I别再回头了。
#include <iostream>

class Big {
 public:
   Big() : living_(true), i_(5) { // This initialization of i is strictly legal but
      void *me = this;            // the result is undefined.
      ::std::cerr << "Big constructor called for " << me << "\n";
   }
   ~Big() {
      void *me = this;
      living_ = false;
      ::std::cerr << "Big destructor called for " << me << "\n";
   }

   bool isLiving() const { return living_; }
   const int &getIref() const;
   const int *getIptr() const;

 private:
   ::std::string s_;
   bool living_;
   const int &i_;
   char stuff[50];
};

const int &Big::getIref() const
{
   return i_;
}

const int *Big::getIptr() const
{
   return &i_;
}

inline ::std::ostream &operator <<(::std::ostream &os, const Big &b)
{
   const void *thisb = &b;
   return os << "A " << (b.isLiving() ? "living" : "dead (you're lucky this didn't segfault or worse)")
             << " Big at " << thisb
             << " && b.getIref() == " << b.getIref()
             << " && *b.getIptr() == " << *b.getIptr();
}

class A {
 public:
   A() : big_(Big()) {}

   const Big &getBig() const { return big_; }

 private:
   const Big &big_;
};

int main(int argc, char *argv[])
{
   A a;
   const Big &b = Big();
   const int &i = 0;
   ::std::cerr << "a.getBig() == " << a.getBig() << "\n";
   ::std::cerr << "b == " << b << "\n";
   ::std::cerr << "i == " << i << "\n";
   return 0;
}
Big constructor called for 0x7fffebaae420
Big destructor called for 0x7fffebaae420
Big constructor called for 0x7fffebaae4a0
a.getBig() == A living Big at 0x7fffebaae420 && b.getIref() == -341121936 && *b.getIptr() == -341121936
b == A living Big at 0x7fffebaae4a0 && b.getIref() == 0 && *b.getIptr() == 0
i == 0
Big destructor called for 0x7fffebaae4a0
 class Foo
    {
    public: 
        Foo(int& a):x(a) {      
         y = 1;
        }
    private:
        int& x;
        int y;
    };