C++三法则和五法则的实例测试

1、基本原则

C++98的三法则:

如果需要析构函数,则一定需要拷贝构造函数和拷贝赋值操作符。一般是因为存在指针, 通过自定义的拷贝构造函数和赋值运算符防治浅拷贝问题,获取管理了系统的资源,需要及时释放掉。

复制(拷贝)构造函数

拷贝赋值操作符  

析构函数

class X  {
public:
  X (const X& lvalue);   //copy constructor
  X& operator=(const X& lvalue);   //copy assignment operator
  ~X();
private:
  T* p;   //means the class is a nontrivial
};

C++11的五法则:

与三之法则不同的是,不提供移动构造函数和移动赋值运算符通常不是错误,但会导致失去优化机会。

复制(拷贝)构造函数

移动构造函数

拷贝赋值操作符

移动赋值操作符

析构函数

class X  {
public:
  X (const X& lvalue);   //copy constructor
  X (X&& rvalue);   //move constructor
  X& operator=(const X& lvalue);   //copy assignment operator
  X& operator=(X&& rvalue);   //move assignment operator
  ~X();
private:
  T* p;   //means the class is a nontrivial
};

2 实例类设计

这是个普通的模板类,实现了五法则,即复制构造函数,赋值操作符,析构函数,移动构造函数,移动操作符。

#pragma once

#include <string>
#include <iostream>
#include <fstream>


template<typename vType>
class Array2D
{
public:
	Array2D(unsigned int nj, unsigned int  ni, std::string name);

	Array2D(const Array2D<vType>& other);
	Array2D<vType>& operator=(const Array2D<vType>& other);
	virtual ~Array2D();

	// Implement Move Semantics
	// Note: It is usually best to mark move operators as noexcept
	//       This allows certain optimizations in the standard library
	//       when the class is used in a container.
	Array2D(Array2D<vType>&& that) noexcept
		:_ni(that._ni)
		, _nj(that._nj)
		,_name(that._name)
		,_datPtr(nullptr)               // Set the state so we know it is undefined
		
	{
		swap(*this, that);
	}

	Array2D<vType>& operator=(Array2D<vType>&& that) noexcept
	{
		swap(*this, that);
		return *this;
	}
	
	unsigned int getNi() { return _ni; }  //column
	unsigned getNj() { return _nj; }   //rows

	unsigned int getNi()const { return _ni; }   //column
	unsigned getNj()const { return _nj; }  //rows

	vType& getValue(unsigned int j, unsigned int i);
	const vType& getValue(unsigned int j, unsigned int i)const;

	void printSelf();
	void printSelf()const;

	void printSelf(std::ofstream&fout);
	void printSelf(std::ofstream&fout)const;

	void printSelf(const std::string & fileName);
	void printSelf(const std::string& fileName)const;

private:
	void swap(Array2D<vType>& lhs, Array2D<vType>& rhs) noexcept;

protected:
	unsigned int _ni;
	unsigned int _nj;
	std::string _name;
	vType* _datPtr{ nullptr };

};



template<typename vType>
inline Array2D<vType>::Array2D(unsigned int nj, unsigned int ni, std::string name)
	:_ni(ni), _nj(nj), _name(name), _datPtr(nullptr) {
	_datPtr = new vType[_ni * _nj];
	
}

template<typename vType>
inline Array2D<vType>::Array2D(const Array2D<vType>& other):
	_ni(other._ni), _nj(other._nj), _name(other._name), _datPtr(nullptr)
{
	_datPtr = new vType[_ni * _nj];
	for (int i = 0; i < _ni * _nj; i++) {
		_datPtr[i] = other._datPtr[i];
	}
}

template<typename vType>
inline Array2D<vType>& Array2D<vType>::operator=(const Array2D<vType>& other)
{
	// Use copy and swap idiom to implement assignment.
	Array2D<vType> copy(other);
	swap(*this, copy);
	return *this;
	
}




template<typename vType>
inline Array2D<vType>::~Array2D()
{
	if (_datPtr != nullptr) {
		delete _datPtr;
		_datPtr = nullptr;
	}
		
}

template<typename vType>
inline vType& Array2D<vType>::getValue(unsigned int j, unsigned int i)
{
	return _datPtr[j * _ni + i];
}

template<typename vType>
inline const vType& Array2D<vType>::getValue(unsigned int j, unsigned int i) const
{
	return _datPtr[j * _ni + i];
}

template<typename vType>
inline void Array2D<vType>::printSelf()
{
	for (int j = _nj - 1; j >= 0; j--) {
		for (int i = 0; i < _ni; i++) {
			std::cout << _datPtr[j * _ni + i] << "\t";
		}
		std::cout << std::endl;
	}
}

template<typename vType>
inline void Array2D<vType>::printSelf() const
{
	for (int j = _nj - 1; j >= 0; j--) {
		for (int i = 0; i < _ni; i++) {
			std::cout << _datPtr[j * _ni + i] << "\t";
		}
		std::cout << std::endl;
	}
}

template<typename vType>
inline void Array2D<vType>::printSelf(std::ofstream& fout)
{
	for (int j = _nj - 1; j >= 0; j--) {
		for (int i = 0; i < _ni; i++) {
			fout << _datPtr[j * _ni + i] << "\t";
		}
		fout << std::endl;
	}
}

template<typename vType>
inline void Array2D<vType>::printSelf(std::ofstream& fout) const
{
	for (int j = _nj - 1; j >= 0; j--) {
		for (int i = 0; i < _ni; i++) {
			fout << _datPtr[j * _ni + i] << "\t";
		}
		fout << std::endl;
	}
}

template<typename vType>
inline void Array2D<vType>::printSelf(const std::string& fileName)
{
	std::ofstream fout(fileName);
	if (!fout.is_open()) {
		std::cout << "fail to open " << fileName << std::endl;
		return;
	}
	printSelf(fout);
	fout.close();
}

template<typename vType>
inline void Array2D<vType>::printSelf(const std::string& fileName) const
{
	std::ofstream fout(fileName);
	if (!fout.is_open()) {
		std::cout << "fail to open " << fileName << std::endl;
		return;
	}
	printSelf(fout);
	fout.close();
}

template<typename vType>
inline void Array2D<vType>::swap(Array2D<vType>& lhs, Array2D<vType>& rhs) noexcept
{
	swap(lhs._ni, rhs._ni);
	swap(lhs._nj, rhs._nj);
	swap(lhs._name, rhs._name);
	swap(lhs._datPtr, rhs._datPtr);
}

3 类的调用测试

#include "Array2D.h"

#include <random>


int main(int argc, char* argv[]) {

	unsigned int ni = 4;
	unsigned int nj = 3;
	Array2D<double> arrayTest{ nj, ni, "test" };
	auto arrayTest2 = arrayTest;
	
	std::random_device dv;
	std::default_random_engine rd(dv());
	std::uniform_real_distribution<double> real_dist;
	for (unsigned int j = 0; j < nj; j++) {
		for (unsigned int i = 0; i < ni; i++) {
			arrayTest.getValue(j, i) = real_dist(rd);
		}
	}
	std::cout << "test1" << std::endl;
	arrayTest.printSelf();
	arrayTest.printSelf("test.txt");

	std::cout << "test2" << std::endl;
	arrayTest2.printSelf();
	arrayTest2.printSelf("test2.txt");

	std::cout << "test3" << std::endl;
	auto arrayTest3 = Array2D<double>(arrayTest);
	arrayTest3.printSelf();
	arrayTest3.printSelf("test3.txt");

	std::cout << "test4" << std::endl;
	auto arrayTest4 = arrayTest;
	arrayTest4.printSelf();
	arrayTest4.printSelf("test4.txt");

	return EXIT_SUCCESS;
}

结果

test1
0.133351        0.995246        0.739061        0.33874
0.523315        0.40387 0.928565        0.817014
0.458272        0.0335825       0.300851        0.202705
test2
-6.27744e+66    -6.27744e+66    -6.27744e+66    -6.27744e+66
-6.27744e+66    -6.27744e+66    -6.27744e+66    -6.27744e+66
-6.27744e+66    -6.27744e+66    -6.27744e+66    -6.27744e+66
test3
0.133351        0.995246        0.739061        0.33874
0.523315        0.40387 0.928565        0.817014
0.458272        0.0335825       0.300851        0.202705
test4
0.133351        0.995246        0.739061        0.33874
0.523315        0.40387 0.928565        0.817014
0.458272        0.0335825       0.300851        0.202705

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

oceanstonetree

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值