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
#include
#include
template
class Array2D
{
public:
Array2D(unsigned int nj, unsigned int ni, std::string name);
Array2D(const Array2D& other);
Array2D& operator=(const Array2D& 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&& 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& operator=(Array2D&& 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& lhs, Array2D& rhs) noexcept;
protected:
unsigned int _ni;
unsigned int _nj;
std::string _name;
vType* _datPtr{ nullptr };
};
template
inline Array2D::Array2D(unsigned int nj, unsigned int ni, std::string name)
:_ni(ni), _nj(nj), _name(name), _datPtr(nullptr) {
_datPtr = new vType[_ni * _nj];
}
template
inline Array2D::Array2D(const Array2D& 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
inline Array2D& Array2D::operator=(const Array2D& other)
{
// Use copy and swap idiom to implement assignment.
Array2D copy(other);
swap(*this, copy);
return *this;
}
template
inline Array2D::~Array2D()
{
if (_datPtr != nullptr) {
delete _datPtr;
_datPtr = nullptr;
}
}
template
inline vType& Array2D::getValue(unsigned int j, unsigned int i)
{
return _datPtr[j * _ni + i];
}
template
inline const vType& Array2D::getValue(unsigned int j, unsigned int i) const
{
return _datPtr[j * _ni + i];
}
template
inline void Array2D::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
inline void Array2D::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
inline void Array2D::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
inline void Array2D::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
inline void Array2D::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
inline void Array2D::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
inline void Array2D::swap(Array2D& lhs, Array2D& 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
int main(int argc, char* argv[]) {
unsigned int ni = 4;
unsigned int nj = 3;
Array2D arrayTest{ nj, ni, "test" };
auto arrayTest2 = arrayTest;
std::random_device dv;
std::default_random_engine rd(dv());
std::uniform_real_distribution 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(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
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)