我是靠谱客的博主 寂寞棒棒糖,最近开发中收集的这篇文章主要介绍默认复制构造函数 默认 赋值运算符产生的问题,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

#include <iostream>
#ifndef _BADSTRING_H_
#define  _BADSTRING_H_


class BadString
{
private: 
	char * str;
	int len;
	static int str_num;
public:
	BadString(const char* s);
	BadString();
	~BadString();
	//BadString & BadString::operator=(const BadString &st);//复制运算符重载
	friend std::ostream & operator<<(std:: ostream & os,const BadString & st);
};
#endif // DEBUG

#include "badstring.h"
#include "cstring"
using std::cout;
using std::endl;
int BadString::str_num = 0;
BadString::BadString(const char * s)
{
	len = strlen(s);
	str = new char[len + 1];
	//str = s;
	strcpy(str, s);
	str_num++;
	cout <<"创建的对象个数为"<<str_num << ":"" << s << ""n";
}
BadString::BadString()
{
	len = 4;
	str = new char[4];
	strcpy(str,"C++");
	str_num++;
	cout << str_num << ":"" << str << ""默认构造函数n";
}
BadString::~BadString()
{
	cout <<"析构了对象"<< str;
	cout << "对象减少到" << str_num << endl;
	--str_num;
	
	delete[]str;
}
//显式复制构造函数 以进行深拷贝 

//赋值运算符重载 ,解决类对象赋值是析构函数出现二次释放str 
//BadString & BadString::operator=(const BadString & st)
//{
	//	if (this == &st)
	//	{
	//		return *this;
	//	}

	//	delete[] str;
	//	len = st.len;
	//	str = new char[len+1];
	//	std::strcpy(str,st.str);
	//	return *this;
//}


//友元函数:非成员函数 但是与成员函数有相同权限
//std::ostream & operator << (std::ostream & os, const BadString & st)
//{
//	os << st.str;
//	return os;
//}

main函数:

#include "badstring.h"
#include <iostream>
using std::cout;
using std::endl;
void callme1(BadString & );
void callme2(BadString );

int main()
{
	cout << "starting an inner block .n";
	BadString name1("胡友呈1");
	BadString name2("胡友呈2");
	BadString name3("胡友呈3");

	cout << "name1" << name1 << endl;
	cout << "name2" << name2 << endl;
	cout << "name3" << name3 << endl;
	callme1(name1);
	callme2(name2);

	BadString anther = name3;//anthor 被初始化为name3 使用复制构造函数 通过定义显示复制构造函数来进行深度复制

	cout << "anthoer" << anther << endl;
	BadString knot;
	knot = name1;//赋值运算的重载
	cout << "knot: " << knot << endl;
	cout << "exit the blockn";
	cout << "End of main()n";
	return 0;

}

void callme1(BadString & rsb)
{
	cout << "String passed by reference :n";
	cout << rsb << "n";
}
void callme2(BadString sb)
{
	cout << "String passed by value :n";
	cout << sb << "n";
}

问题一:


main 函数中 callme2(name2)函数参数是按照值进行传递,导致callme2执行完了调用了析构函数。

使得对象name2已经释放,再次使用它时已经无法识别原始字符。

 问题二:

本程序使用了一个对象来初始化另一个对象,编译器将自动生成其构造函数(称为复制构造函数),自动生成的构造函数并不知道更新静态变量num_string,因此打乱对象计数。

使用 一个对象来初始化另一个对象:

BadString anther = name3;

其对应的复制构造函数的原型:

BadString (const BadString &);

默认的复制构造函数逐个复制非静态成员(成为浅复制),复制的是成员的值。

下述语句:

BadString anther = name3;

可以等效为下面的功能(当然下面语句代码编译不能通过,因为私有成员是无法访问的):

BadString  sailor;

sailor.str = sports.str;

sailor.len =sports.len;

使用默认复制构造函数导致的问题:

1)创建对象计数并未增加


2)anther已经将name3的字符串析构,而name3再次析构会导致字符串无法找到其地址出现乱码。

通过显示构造函数解决该问题。

问题三:

赋值运算符重载:

kont =name1;

当函数正常调用kont 析构函数 ,其显示正常

但是name1 进行析构释放的时候就会出现乱码,因为kont.str 与name1.str指向的地址相同

通过重构=提供赋值运算符的定义。


对于上述问题进行:

解决方案:

#include <iostream>
#ifndef _BADSTRING_H_
#define  _BADSTRING_H_

class BadString
{
private: 
	char * str;
	int len;
	static int str_num;
public:
	BadString(const char* s);
	BadString(const BadString & s);
	BadString();
	~BadString();
	BadString & BadString::operator=(const BadString &st);
	friend std::ostream & operator<<(std:: ostream & os,const BadString & st);
};
#endif // DEBUG
#include "badstring.h"
#include "cstring"
using std::cout;
using std::endl;
int BadString::str_num = 0;
BadString::BadString(const char * s)
{
	len = strlen(s);
	str = new char[len + 1];
	//str = s;
	strcpy(str, s);
	str_num++;
	cout <<"创建的对象个数为"<<str_num << ":"" << s << ""n";
}
BadString::BadString(const BadString & s)
{

	str_num++;
	len = s.len;
	str = new char[len + 1];
	std::strcpy(str, s.str);
	cout << "创建的对象个数为" << str_num << ":"" << s << ""n";
}
BadString::BadString()
{
	len = 4;
	str = new char[4];
	strcpy(str,"C++");
	str_num++;
	cout << str_num << ":"" << str << ""默认构造函数n";
}
BadString::~BadString()
{
	cout <<"析构了对象"<< str;
	cout << "对象减少到" << str_num << endl;
	--str_num;
	
	delete[]str;
}
//显式复制构造函数 以进行深拷贝 


//赋值运算符重载 ,解决类对象赋值是析构函数出现二次释放str 
BadString & BadString::operator=(const BadString & st)
{
		if (this == &st)
		{
			return *this;
		}

		delete[] str;
		len = st.len;
		str = new char[len+1];
		std::strcpy(str,st.str);
		return *this;
}

//友元函数:非成员函数 但是与成员函数有相同权限
std::ostream & operator << (std::ostream & os, const BadString & st)
{
	os << st.str;
	return os;
}
#include "badstring.h"
#include <iostream>
using std::cout;
using std::endl;
void callme1(BadString & );
void callme2(BadString & );

int main()
{
	
	{
		cout << "starting an inner block .n";
	BadString name1("张三 1 号 ");
	BadString name2("张三 2 号 ");
	BadString name3("张三 3 号 ");

	cout << "name1" << name1 << endl;
	cout << "name2" << name2 << endl;
	cout << "name3" << name3 << endl;
	callme1(name1);
	cout << "name1" << name1 << endl;
	callme2(name2);
	cout << "name2" << name2 << endl;
	BadString anther = name3;//anthor 被初始化为name3 使用复制构造函数 通过定义显示复制构造函数来进行深度复制

	cout << "anthoer" << anther << endl;
	BadString knot;
	knot = name1;//赋值运算的重载
	cout << "knot: " << knot << endl;
	cout << "exit the blockn";
}
	cout << "End of main()n";

	return 0;

}

void callme1(BadString & rsb)
{
	cout << "String passed by reference :n";
	cout << rsb << "n";
}
void callme2(BadString & sb)
{
	cout << "String passed by value :n";
	cout << sb << "n";
}









最后

以上就是寂寞棒棒糖为你收集整理的默认复制构造函数 默认 赋值运算符产生的问题的全部内容,希望文章能够帮你解决默认复制构造函数 默认 赋值运算符产生的问题所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(55)

评论列表共有 0 条评论

立即
投稿
返回
顶部