调用了Copy构造函数而不是赋值运算符
Copy Constructor invoked instead of assignment operator
考虑以下自包含代码。
#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)是一项任务,而不是一个复制指令。然而,当编译(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)编译得很好,没有任何错误。
您的赋值运算符按值获取参数,这需要进行复制。该副本可以(也可以不)被消除,但副本构造函数仍然需要可用和可访问,即使没有被调用。
有两个问题:
- 您的私有赋值运算符
Foo& operator=(Foo&);
采用非常量左值引用。这意味着它不能在nb = Foo<int>(10);
中被选择为重载,因为RHS是一个右值 - 这将导致您的模板分配运算符被选中。但这需要一个复制或移动复制构造函数,从而按值获取参数
如果你修复了1。为了获取const
参考,gcc给出以下错误:
错误:'Foo&Foo::operator=(const Foo&)[with Ty=int]'是专用
如果你修复2。使得模板赋值运算符采用const
引用,代码编译无误。
您的赋值运算符按值传递参数,因此它使用复制ctor:
template<typename U>
Foo& operator=(Foo<U> rv)
通过常量引用传递的可能解决方案:
template<typename U>
Foo& operator=(const Foo<U> &rv)
专用版本
private:
Foo(Foo&);
Foo& operator=(Foo&);
无法调用,因为它采用了非常量左值引用,因此
Foo& operator=(Foo<U> rv)
此版本被调用,但它通过值获取参数,并且必须调用复制构造函数。
相关文章:
- 复制构造函数、赋值运算符C++
- C++ 基本 CTOR 说明 - 为什么不调用赋值/复制构造函数
- 为用户定义的类正确调用复制构造函数/赋值运算符
- C++矢量复制构造函数和赋值运算符是否也复制保留空间?
- 非模板 std::reference_wrapper赋值运算符和模板构造函数
- 复制构造函数和赋值运算符的值类实现
- 在C++中,我可以在定义自己的复制构造函数后跳过定义赋值运算符吗?
- 为什么我的类工作正常,即使在返回垃圾值作为赋值运算符和空复制构造函数的返回之后
- 禁止复制构造函数和赋值运算符singleton类
- 复制构造函数和复制赋值运算符是否应具有相同的语句?
- 重载赋值运算符函数和复制构造函数中的错误
- 构造函数中的赋值运算符
- 为什么定义移动构造函数会删除移动赋值运算符
- 为什么可以使用已删除的移动构造函数和赋值运算符移动对象?
- 模板的赋值运算符(成员函数)实现的正确语法
- 错误的数组初始化与赋值副本构造函数初始化
- 赋值复制构造函数
- 赋值给构造函数中的常量变量
- 成员初始化列表vs赋值/复制构造函数(在boost deadline_timer中)
- 将传递的对象赋值给构造函数中的成员对象