内部类中带有引用成员的默认赋值运算符

7

我遇到了一个我不理解的问题,希望这里的某个人可以提供一些见解。简化后的代码如下(原始代码是自定义队列/队列迭代器实现):

class B
{
public:
    B() {};
    class C
    {
    public:
        int get();
        C(B&b) : b(b){};
    private:
        B& b;
    };
public:
    C get_c() { return C(*this); }
};

int main()
{
    B b;
    B::C c = b.get_c();


    c = b.get_c();
    return EXIT_SUCCESS;
}

当我编译这段代码时,会出现以下错误:

foo.cpp: In member function 'B::C& B::C::operator=(const B::C&)':
foo.cpp:46: error: non-static reference member 'B& B::C::b', can't use default assignment operator
foo.cpp: In function 'int main()':
foo.cpp:63: note: synthesized method 'B::C& B::C::operator=(const B::C&)' first required here

我可以通过使用两个独立的C变量来避开这个问题,因为它们应该是独立的'C'对象,但这只是隐藏了问题(我仍然不明白为什么我不能这样做)。

我认为原因是引用无法复制,但我不明白为什么。我需要提供自己的赋值运算符和复制构造函数吗?

4个回答

13

这个问题与内部类无关。在C++中,你不能(重新)分配引用 - 它们需要在定义时初始化。

一个更简单的例子是:

class B
{
public:
    B(int& i) : ir(i) {};

    int& ir;
};


int main()
{
    int i;
    B b(i);      // Constructor - OK

    int j;
    B bb = B(j); // Copy constructor - OK

    bb = b;      // Assignment - Error
    return 0;
}

当然,你是正确的,我简直不敢相信我错过了那么明显的解释。早上应该多喝点咖啡:D - laura
2
+1. 我发现在谈论引用时习惯性地使用“绑定”而不是“赋值”,可以帮助我避免犯这个错误。 - Kaz Dragon
现在,我将重新分配一个引用,当然它会编译通过:int a = 3; int b = 4; int& ref = a; ref = b;。因此,重新分配引用是可行的。 - friko

6

给定初始值后,引用就不能再更改。这意味着无法编写赋值运算符来更改引用成员的值。如果需要这样做,请使用指针而不是引用。


这是完全可能的。请查看下面我的评论以获取详细信息。 - rmn

3
实际上,这个问题是有解决方案的。你可以通过实现基于复制构造函数的赋值运算符来解决它,并且它会有效地工作 :) 对于这种情况,这是一种非常有能力的技术。假设你确实想支持赋值操作。

1
在赋值运算符中调用析构函数是一个非常糟糕的编程习惯。 - Sjoerd
1
首先感谢您的回答,我已经自己找到了这个解决方案,但是省略了自我赋值检查和显式析构函数调用。您指出不建议使用它(我同意您的理由),鉴于这些缺点,是否有更好的实现方式? - davetapley
你的链接已经失效了,现在你的答案是无效的。 - user

0

C++没有"内部类",只有嵌套类声明。 "内部类"是Java的一个特性,在其他主流语言中不常见。在Java中,内部类很特殊,因为它们包含对包含类型对象的隐式不可变引用。要在Java中实现与C++的嵌套声明相当的功能,需要使用静态内部类;静态内部类不包含对声明类型对象的引用。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接