原标题:类模板重载赋值运算遇到的几个问题
先说错因:没有重载复制构造函数
代码
#include<iostream>
#include<iomanip>
using namespace std;
template<typename T>
class Array {
public:
Array(int=5);
Array(const Array<T>&);
~Array();
T getsum()const;
void show()const;//输出数组内每个元素
T& operator[] (int);
Array<T>& operator=(const Array<T>&);
private:
T* a;
int len;
};
template<typename T>
Array<T>::Array(int length)
:len(length > 0 ? length : 5)
{
a = new T[len];
if (a == NULL) {//异常退出
cout << "ERROR! Failed to allocate memory successfully!" << endl;
exit(1);
}
//正常则进行初始化
for (int i = 0; i < len; i++)
a[i] = 0;
}
//复制构造函数
template<typename T>
Array<T>::Array(const Array<T>& arr) {
cerr << "construction ing!";
system("pause");
len = arr.len;
a = new T[len];
if (a == NULL) {//异常退出
cout << "ERROR! Failed to allocate memory successfully!" << endl;
exit(1);
}
for (int i = 0; i < len; i++) {
a[i] = arr.a[i];
}
}
template<typename T>
Array<T>::~Array() {
delete[]a;
a = NULL;
}
template<typename T>
T Array<T>::getsum()const {
T temp = 0;
for (int i = 0; i < len; i++)
temp += a[i];
return temp;
}
template<typename T>
void Array<T>::show()const {
for (int i = 0; i < len; i++) {
cout << a[i] << " ";
}
cout << endl;
}
template<typename T>
T& Array<T>::operator[](int p) {
if (p<0 || p>this->len - 1)
throw invalid_argument("out of range!");
else
return (this->a)[p];
}
template<typename T>
Array<T>& Array<T>::operator=(const Array<T>& arr) {
cerr << "= ing!" << endl;
system("pause");
if (this!=&arr){
if (len != arr.len) {
delete[] a; //删掉这句程序可以正常运行
len = arr.len;
a = new T[len];
}
for (int i = 0; i < len; i++) {
a[i] = arr.a[i];//arr[i]不行
}
}
return *this;
}
template<typename T>
void swap_2(T& a, T& b) {
T temp = b;//本句调用了复制构造函数
b = a;//以下两句皆调用赋值运算符
a = temp;
}
int main() {
int n, m;
cin >> n >> m;
Array<int> intArray1(n);
Array<int> intArray2(m);
for (int i = 0; i < n; i++)
cin >> intArray1[i];
for (int i = 0; i < m; i++)
cin >> intArray2[i];
swap_2(intArray1, intArray2);
intArray1.show();
intArray2.show();
return 0;
}
问题
提示已触发断点 未加载 wntdll.pdb
加载符号服务器无效
解决
最终解决发现 在swap中 创建一个新对象时 用另一个对象初始化它
此时需要调用 复制构造函数
复制构造函数调用的情形
①当函数的参数为类的对象时
②函数的返回值是类的对象
③对象需要通过另外一个对象进行初始化
参考自:c++拷贝构造函数详解
疑问1
为什么在不加复制构造函数的情况下
Array& Array::operator=(const Array& arr) {
cerr << “= ing!” << endl;
system(“pause”);
if (this!=&arr){
if (len != arr.len) {
delete[] a;
len = arr.len;
a = new T[len];
}
删去 delete[] 可以运行(如图 未调用复制构造函数)(重载赋值中)
正常运行截图
2020.4.5
疑问1解答
4月6日更新:
考虑到产生上述问题的原因 可能是由于调用**默认复制构造函数** 而造成的 浅拷贝
进行如下尝试 在swap函数上加入断点 发现
void swap_2(T& a, T& b) {
T temp = b;
b = a;
a = temp;
}
在删掉重载的复制构造函数后 实际上调用的是默认复制构造函数
Array(const Array&)=delete; //删除默认拷贝构造函数
当进行
b=a;
此时调用了重载赋值(=)运算符使得 b中的指针所指向的内存被释放
由于temp对象进行的是浅拷贝
temp对象中的指针变成了野指针
跳出swap函数后就会触发如下断点:
疑问2
- 至于为什么在结束交换时触发断点 笔者目前才疏学浅 技艺不精 暂时不能解答
留待日后解决 恳请大佬指点
补充
今天又遇到了这个问题
错音是
指针指向越界。
解决方案: 取消指针对非法地址的指向。
试图对非 new 申请的内存用 delete 进行释放,只有用new申请的内存才能用 delete 来释放,其他只能由系统自动释放。
解决方案: 删除释放该内存的 delete 语句。