交换两个类对象时引发的未加载wntdll.pdb报错

交换两个类对象时引发的未加载wntdll.pdb报错

原标题:类模板重载赋值运算遇到的几个问题

先说错因:没有重载复制构造函数

代码

#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[] 可以运行(如图 未调用复制构造函数)(重载赋值中)
删去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 语句。
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值