【问题标题】:Reference variable with error, must be initialized in constructor base/member initializer有错误的引用变量,必须在构造函数基/成员初始化程序中初始化
【发布时间】:2012-10-15 06:36:19
【问题描述】:

当我尝试编译下面的源代码时出现以下错误。谁能描述为什么会出现这个错误以及我该如何解决?

错误 1 ​​错误 C2758: 'A::s_' : 必须在构造函数基/成员初始化器中初始化

#include <iostream>
#include <string>

using namespace std;

class A
{
public:
    A(string& s) : s_(s) { cout << "A::ctor" << endl; }
    A(const A& rhs)      { cout << "A::copy" << endl; }
    ~A()                 { cout << "A::dtor" << endl; }

    A& operator=(const A& rhs) { cout << "A::copyassign" << endl; }

private:
    string& s_;    
};

int main()
{

    return 0;
}

【问题讨论】:

  • 当你有一个引用成员时,你不能真正拥有一个语义上有效的赋值运算符。您不能将其重新分配给不同的字符串。它只会修改被引用的原始字符串。

标签: c++ constructor compiler-errors visual-studio-2012


【解决方案1】:

首先,您的A::s_ 是对std::string 的引用;这意味着它引用了必须存在于某处的东西。

由于他的引用类型,以及引用必须在创建时初始化的事实,您必须在所有A 构造函数中初始化A::s_(正如其他用户所指出的那样):

class A
{
public:
    A(string& s) : s_(s)
    { cout << "A::ctor" << endl; }

    A(const A& rhs) : s_(rhs.s_) // <-- here too!!
    { cout << "A::copy" << endl; }

    ~A()
    { cout << "A::dtor" << endl; }

    A& operator=(const A& rhs)
    { cout << "A::copyassign" << endl; }

private:
    string& s_;    
};

现在,回到我提到的第一件事; A::s_ 必须引用存在的东西,所以你必须知道一些东西,看看下面的代码:

int main()
{
    // New A instance:
    A a("hello world");

    return 0;
}

在构造这个A 实例时,我们提供了一个const char[12] 值,使用这个值创建一个临时的std::string 并提供给A::A(string&amp; s) 构造函数。构造函数结束后A::s_ 在哪里引用?创建的临时std::string 会发生什么?当Aconstructor 结束时,它的生命周期是延长了还是死亡?您确定参考是您需要的吗?

std::string s("hello world");

int main()
{
    // New A instance:
    A a(s);

    return 0;
}

使用上面的代码,创建了一个新的A 实例,调用相同的A::A(string&amp; s) 构造函数,但提供的字符串位于全局范围内,因此它不会被销毁,而A::s_ 来自@ 987654340@ 实例在其整个生命周期中都会引用一个有效的字符串,但真正的威胁在于复制构造函数:

std::string s("hello world");

int main()
{
    A a(s);    // a.s_ references the global s.
    A b(a);    // b.s_ references the a.s_ that references the global s.

    return 0;
}

复制的对象值将引用给定对象的std::string!这就是你想要的吗?

【讨论】:

  • 非常感谢您的详细描述。
  • 我只想指出,你不能首先将"hello world" 传递给它(即编译器错误),因为临时对象不能绑定到非常量引用。跨度>
  • @chris it worked 给我。在A a("hello world") 调用中创建的临时对象绑定到a.s_ 引用。
  • 我的错!你是对的!傻我! :( 这证明了将std::string 引用为成员并使用非显式构造函数比我想象的还要糟糕!
【解决方案2】:

您的复制构造函数从不初始化引用。确保这样做:

A(const A &rhs) : s_(rhs.s_) {cout << "A::copy" << endl;}

【讨论】:

    【解决方案3】:
     string& s_;
    

    这是一个参考变量。当对象被分配时它应该有一个值,因为这是对象的一部分,这就是为什么应该使用构造函数的初始化列表来初始化这个属性。

    如果您不需要将此属性作为对象的一部分,则可以使用指针而不是引用:

     string* s_;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-03
      • 1970-01-01
      • 1970-01-01
      • 2011-05-02
      • 2014-07-02
      • 1970-01-01
      相关资源
      最近更新 更多