构造函数的多种初始化方式

文章详细介绍了C++中类的构造函数,包括默认构造函数的定义方式,拷贝构造函数的作用以及浅拷贝和深拷贝的区别。此外,还讨论了移动构造函数在资源管理中的优势,以及如何防止资源泄漏和处理自我分配的情况。对于不需要拷贝或移动操作的类,应明确禁用相关操作。
摘要由CSDN通过智能技术生成

在大型系统中初始化一个类时,一般模板为

class B 
{
public:
	B();\\默认构造
	\\B(const int& a = 0, const int &b = 0);\\默认构造
	B(const B& other);

	~B();
private:
	int a;
	int b;
};


B::B(const int& a = 0, const int& b = 0)
{
	this->a = a;
	this->b = b;
}

B::B(const B& other):a(other.a),b(other.b){}

B::~B(){}

默认构造:

B(const int& allocator = 0);//默认构造

注意:

1、只有当没有定义任何构造函数时,编译器才会提供默认构造函数。

2、定义默认构造函数的方式有两种,一种是给已有构造函数的所有参数提供默认值,另一个是通过函数重载定义一个构造函数-没有参数的构造函数,例如B()

拷贝构造:

B(const B& other);

浅拷贝(默认拷贝函数):将原对象或原数组的引用直接赋值给新对象,新对象只是原对象的一个引用。

深拷贝:创建一个新的独享和数组,将原对象的各项属性的“值”(数组的所有元素)拷贝过来。

深拷贝会在堆内存中另外申请空间存储数据,从而解决了指针悬挂问题,当数据成员中有指针时,必须使用深拷贝。

若拷贝对象里的元素只有值,没有引用,那么深拷贝和浅拷贝时相同的。

当派生类使用new进行动态内存分配时,需要为派生类显示定义显示析构函数,拷贝构造函数和赋值运算符。

class baseDMA
{
private:
	char* label;
public:
	baseDMA(const baseDMA& rs);
	virtual ~baseDMA();
};

class hasDMA :public baseDMA
{
private:
	char* style;
public:
	hasDMA(const hasDMA& hs);
    virtual ~hasDMA();
};

hasDMA::hasDMA(const hasDMA& hs)
	: baseDMA(hs)
{
	style = new char[std::strlen(hs.style) + 1];
	strcpy(style, hs.style);
}

初始化列表写法:

B::B(const B& other):a(other.a),b(other.b){}

变量必须一一对应才能传参

移动构造

c++标准库使用比如vector::push_back等这类函数时,会对参数的对象进行复制,连数据也会复制,这就会造成对象内存的额外创建。

C++提供了std::move函数来把左值转换为右值,而且新版的push_back也支持&&参数的重载版本,这时候就可以高效率的使用内存了

对指针类型的标准库对象不需要这么做

移动构造相对于深拷贝构造来说,移动构造占用的资源更少。

#include <memory>
#include <iostream>
#include <vector>

using namespace std;

class moveTest
{
public:
	explicit moveTest(int length):m_length(length),m_data(new int[length])
	{
		cout << "In moveTest(size_t).length = "
			<< m_length << "." << endl;
	}

	moveTest(moveTest && other) noexcept
		:m_data(nullptr),
		m_length(other.m_length)
	{
		cout << "In moveTest (moveTest && other)" << endl;
		*this = std::move(other);
	}

	moveTest& operator = (moveTest&& other) noexcept
	{
		std::cout << "In operator = (mapTest&&).length"
			<< other.m_length << "." << endl;

		if (this != &other)
		{
			// free the existing resource
			delete[] m_data;

			//copy the data pointer from the
			//source object
			m_data = other.m_data;
			m_length = other.m_length;

			//release the data pointers from the source object 
			//so that destructor does not free the memory multiple times

			other.m_data = nullptr;
			other.m_length = 0;
		}

		return *this;
	}

	~moveTest()
	{
		cout << "In ~moveTest().length = "
			<< m_length << ".";

		if (m_data != nullptr)
		{
			cout << "Deleting resource";
			delete[] m_data;
		}

		cout << endl;
	}

private:
	size_t m_length;
	int* m_data;
};

int main()
{
	int a, b;

	a = 5;

	b = std::move(a);

	vector<moveTest> testVec;

	testVec.push_back(moveTest(5));

	testVec.push_back(moveTest(10));

	testVec.push_back(moveTest(15));

	testVec.push_back(moveTest(20));

	return 0;
}

未防止资源泄漏,请始终在移动分配符中释放资源(例如内存,文件句柄和套接字)

为防止无法恢复的资源破坏,请在移动分配运算符中正确处理自我分配

如果你的类不需要拷贝/移动操作,请显式的通过在public域中(private本身就是不能显式直接调用的)使用 = delete或其他手段禁用之;

//Myclass is neither copyable nor movable
MyClass(const MyClass&) = delete;
MyClass operator=(const MyClass &) = delete;

转载自:

https://blog.csdn.net/zhoumoon/article/details/108276324

参考:

【C++】类和对象(二)构造函数&&析构函数&&拷贝构造函数_猪皮兄弟的博客-CSDN博客

C++——深拷贝和浅拷贝_c++ 深拷贝_Verdure的博客-CSDN博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值