在大型系统中初始化一个类时,一般模板为
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
参考: