表达式模板实现数组类时operator=冗余重载的规避方法问询
解决方法:避免显式定义Array_1d拷贝赋值运算符,让模板版operator=生效
核心原因分析
你遇到的问题根源有两点:
- 编译器禁用默认拷贝赋值运算符:因为你的
Array_1d类包含const int itot成员——C++标准规定,当类有const或引用成员时,编译器不会自动生成默认的拷贝赋值运算符(默认赋值逻辑会尝试修改这些不可变成员,这是非法操作)。 - 模板版operator=不能充当拷贝赋值运算符:C++标准明确要求,拷贝赋值运算符必须是非模板的成员函数。哪怕你的模板
operator=可以实例化为Array_1d& operator=(const Array_1d&)的签名,编译器在查找拷贝赋值运算符时,也不会将模板函数纳入候选范围。因此当你尝试给Array_1d赋值另一个Array_1d(比如b(7,10) = a(1,4))时,编译器找不到合法的拷贝赋值运算符,就会报错。
解决方案:删除默认拷贝赋值运算符,引导编译器使用模板版
你可以通过显式删除默认拷贝赋值运算符,让编译器转向匹配你的模板版operator=。具体步骤如下:
移除你写的非模板拷贝赋值运算符:删掉这段重复代码:
inline Array_1d& operator= (const Array_1d& __restrict__ expression) { for (int i=0; i<itot; ++i) (*this)(i) = expression(i); return *this; }显式删除默认拷贝赋值运算符:在类的public区域添加一行声明:
Array_1d& operator=(const Array_1d&) = delete;
修改后,当你执行b = a(1,4)这类赋值操作时,编译器会发现默认拷贝赋值运算符已被删除,转而寻找其他匹配的operator=——此时你的模板版operator=会被自动实例化为Array_1d& operator=(const Array_1d&),并正常执行逻辑。
额外提示
- 你的类当前存在内存泄漏问题:析构函数
~Array_1d()是空的,没有释放data指向的动态数组。建议修改析构函数:~Array_1d() { delete[] data; } - 注意数组大小匹配:模板版
operator=不会检查两边数组的itot是否一致,若赋值的两个Array_1d大小不同,会导致数组越界行为。可以考虑在模板operator=中添加断言来规避风险:#include <cassert> template<class T> inline Array_1d& operator= (const T& __restrict__ expression) { // 若要检查Array_1d类型的大小,需将itot改为public或提供getter方法 assert(itot == expression.itot && "Array size mismatch in assignment!"); for (int i=0; i<itot; ++i) (*this)(i) = expression(i); return *this; }
内容的提问来源于stack exchange,提问作者Chiel
相关产品推荐
相关产品推荐

