复制构造函数而不是赋值运算符

时间:2014-09-09 20:54:04

标签: c++

考虑以下自包含代码。

#include <iostream>
template<typename Ty>
class Foo {
private:
    Ty m_data;
public:
    Foo() :m_data() {}
    Foo(Ty data) :m_data(data) {}
    template<typename U>
    Foo& operator=(Foo<U> rv)
    {
        m_data = rv.m_data;
        return *this;
    }
private:
    Foo(Foo&);
    Foo& operator=(Foo&);
};
int main()
{
    Foo<int> na(10);
    Foo<int> nb;
    nb = Foo<int>(10); // (1)
    Foo<int>(10); // (2)
}

我的理解是声明(1)是一个赋值而不是复制COnstructor。然而,在编译(VC ++和G ++)时,错误消息指出,它尝试匹配被声明为私有的复制构造函数。

1>Source.cpp(23): error C2248: 'Foo<int>::Foo' : cannot access private member declared in class 'Foo<int>'
1>          Source.cpp(16) : see declaration of 'Foo<int>::Foo'

我的问题是,为什么它会尝试搜索复制构造函数而不是分配。

注意,我知道失败的分配是因为(2)编译没有任何错误。

4 个答案:

答案 0 :(得分:4)

您的赋值运算符按值获取其参数,这需要复制。该副本可能(或可能不)被删除 - 但复制构造函数仍需要可用且可访问,即使未被调用。

答案 1 :(得分:3)

两个问题:

  1. 您的私有赋值运算符Foo& operator=(Foo&);采用非常量左值引用。这意味着它不能被选为nb = Foo<int>(10);中的重载,因为RHS是一个右值
  2. 这会导致您的模板分配操作符被选中。但是这需要按值进行参数化,需要复制或移动复制构造函数。
  3. 如果您修复1.以获取const引用,则gcc会出现以下错误:

      

    错误:&#39; Foo&amp; Foo :: operator =(const Foo&amp;)[with Ty = int]&#39;是私人的

    如果你修复了2.所以模板赋值运算符采用const引用,代码编译时没有错误。

答案 2 :(得分:0)

您的赋值运算符按值传递参数,因此它使用copy ctor:

template<typename U>
Foo& operator=(Foo<U> rv)

通过const引用传递它的可能解决方案:

template<typename U>
Foo& operator=(const Foo<U> &rv)

答案 3 :(得分:-1)

私人版

private:
    Foo(Foo&);
    Foo& operator=(Foo&);

无法调用,因为它采用非常量左值引用,所以

Foo& operator=(Foo<U> rv)

调用此版本但它需要参数按值,并且必须调用复制构造函数。