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

posted @ 2022-08-21 10:12  Oliver2022  阅读(78)  评论(0编辑  收藏  举报