c++系列文章目录
提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
一、C++几种常用的函数是什么?
C++11六大函数(构造函数,移动构造函数,移动赋值操作符,复制构造函数,赋值操作符,析构函数)。
一、构造函数
二、移动构造函数
三、移动赋值操作符
四、复制构造函数
五、赋值操作符
六、析构函数
class Temp
{
public:
Temp(const char* str = nullptr);//构造函数
Temp(Temp&& t); //移动构造函数 浅拷贝
Temp& operator = (Temp&& t); //移动赋值操作符,重载=操作符 浅拷贝
Temp(const Temp& t); //复制构造函数 深拷贝
Temp& operator = (Temp& t); //复制赋值操作符 深拷贝
~Temp(void); //析构函数
public:
char* m_pData;
};
//构造函数
Temp::Temp(const char* str)
{
if (!str){
m_pData = nullptr;
}
else{
this->m_pData = new char[1];
*m_pData=*str;
}
cout<<"构造函数:"<<m_pData<<endl;
}
//复制构造函数
Temp::Temp(const Temp& t)
{
if (!t.m_pData){
this->m_pData = nullptr;
}
else{
this->m_pData = new char[1]; //深复制
*m_pData=*t.m_pData;
}
cout<<"复制构造函数1:"<<m_pData<<endl;
//cout<<"复制构造函数2:"<<t.m_pData<<endl;
}
//析构函数
Temp::~Temp(void)
{
if (this->m_pData){
delete[] this->m_pData;
this->m_pData = nullptr;
//cout<<"delete析构函数"<<endl;
}
cout<<"析构函数"<<endl;
}
//复制赋值操作符
Temp& Temp::operator=(Temp& t)
{
if (this != &t){
delete[] this->m_pData;
if (!t.m_pData){
this->m_pData = nullptr;
}
else{
this->m_pData = new char[1]; //深复制
*m_pData=*t.m_pData;
}
}
cout<<"复制赋值操作符1:"<<m_pData<<endl;
//cout<<"复制赋值操作符2:"<<t.m_pData<<endl;
return *this;
}
//移动构造函数
Temp::Temp(Temp&& t)
:m_pData(move(t.m_pData))
{
t.m_pData = nullptr;
cout<<"移动构造函数:"<<m_pData<<endl;
}
//移动赋值操作符,重载=操作符
Temp& Temp::operator=(Temp&& t)
{
assert(this != &t); //assert作用是如果它的条件返回错误,则终止程序执行
this->m_pData = nullptr;
this->m_pData = move(t.m_pData);
t.m_pData = nullptr;
cout<<"移动赋值操作符:"<<this->m_pData<<endl;
return *this;
}
二、优化过程
1.源代码
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <stdio.h>
#include <unistd.h>
#include <queue>
#include <deque>
#include <memory>
#include <string.h>
class C
{
public:
C(){
std::cout<< "C构造函数" <<std::endl;
}
~C(){
std::cout<< "C析构函数" <<std::endl;
}
C(const C& c){
std::cout<< "C复制构造函数" <<std::endl;
}
C(C&& c){
std::cout<< "C移动构造函数" <<std::endl;
}
C& operator = (C& c){
std::cout<< "C复制赋值操作符" <<std::endl;
}
C& operator = (C&& t){
std::cout<< "C移动赋值操作符" <<std::endl;
}
private:
};
using CPtr = std::shared_ptr<C>;
class A
{
public:
A(){
std::cout<< "A构造函数" <<std::endl;
pChar.reset(new char[128]);
memcpy(pChar.get(),"hello",128);
}
~A(){
std::cout<< "A析构函数" <<std::endl;
}
A(const A& a){
std::cout<< "A复制构造函数" <<std::endl;
}
A(A&& a){
std::cout<< "A移动构造函数" <<std::endl;
}
A& operator = (A& a){
std::cout<< "A复制赋值操作符" <<std::endl;
}
A& operator = (A&& t){
std::cout<< "A移动赋值操作符" <<std::endl;
}
void print(){
std::cout<< "string is : "<< pChar.get() <<std::endl;
}
private:
C c;
std::shared_ptr<char> pChar;
};
using APtr = std::shared_ptr<A>;
template<class T>
class BlockingQueue {
public:
BlockingQueue() : _data(), _mutex(), _condition() {}
BlockingQueue(const BlockingQueue &) = delete;
BlockingQueue &operator=(const BlockingQueue &) = delete;
void push(T &&value) {
std::unique_lock<std::mutex> lock(_mutex);
_data.emplace(value);
_condition.notify_one();
}
void push(const T &value) {
std::unique_lock<std::mutex> lock(_mutex);
_data.push(value);
_condition.notify_one();
}
size_t size() const {
std::unique_lock<std::mutex> lock(_mutex);
return _data.size();
}
void clear(){
std::unique_lock<std::mutex> lock(_mutex);
std::queue<T> empty;
swap(empty, _data);
_condition.notify_one();
}
bool wait_for(unsigned int timeout, T *pData = nullptr) {
std::unique_lock<std::mutex> lock(_mutex);
if(_data.empty()){
while (_condition.wait_for(lock,std::chrono::seconds(timeout)) == std::cv_status::timeout) {
std::cout << '.';
}
}
if (pData) *pData = std::move(_data.front());
_data.pop();
return true;
}
private:
std::queue<T> _data;
std::mutex _mutex;
std::condition_variable _condition;
};
int main()
{
BlockingQueue<A> myworlds2;
{
std::thread([&](){
A val;
myworlds2.wait_for(10,&val);
//val.print();
}).detach();
A a2;
myworlds2.push(a2);
}
return 0;
}
发现上面调用,即便我们使用右值等,仍然会多次调用构造、拷贝构造、析构函数等。
2.源代码
对于大内存、上面的操作不仅仅会让我们绕晕,云里雾里,C++功底不够的时候,建议不要按照上面的方法进行构造类对象,那么我们有个“简单高效的方法”可以解决上面的多次创建与销毁。
1、采用智能指针来传递对象
2、类中定义大对象,建议用智能指针管理
新增方法如下:
bool wait_for(unsigned int timeout, T &pData) {
std::unique_lock<std::mutex> lock(_mutex);
if(_data.empty()){
while (_condition.wait_for(lock,std::chrono::seconds(timeout)) == std::cv_status::timeout) {
std::cout << '.';
}
}
pData = _data.front();
_data.pop();
return true;
}
调用实现代码如下:
BlockingQueue<APtr> myworlds3;
{
std::thread([&](){
std::shared_ptr<A> pData;
myworlds3.wait_for(10,pData);
//pData->print();
//std::cout<< "get a A instance" <<std::endl;
}).detach();
APtr APtrInst = std::make_shared<A>();
myworlds3.push(APtrInst);
}
总结
本文讲了一种最最最简单的对象之间的传递,可以减少引用与拷贝,另外不需要过度的理解含义,就可以避免问题的出现。