網站首頁 編程語言 正文
前言
在說移動語義之前 本文作者假設你已經具備了深拷貝淺拷貝左值右值等基本概念 本文不會再過多敘述 那么接下來 讓我們開始吧
Tips:(警告 警告 警告 警告)在閱讀本文章之前 作者首先提醒 線代編譯器有RVO和NRVO等一系列優化策略 除非你明確知道你要使用std::move 不然我并不是很推薦你使用移動語義 他很有可能是無意義的
移動構造
在說移動語義之前 讓我們先來說說移動構造這玩意
我們都知道 深拷貝是會把在堆區的內存一起拷貝的 那么如果我們明確知道一個對象并不會再繼續使用 但是同時我們又想拿到他堆區的資源的時候 我們應該怎么辦呢? 移動構造給我們提供了這種能力 代碼如下所示:
class MoveClass
{
public:
int* p;
MoveClass()
{
p = new int();
std::cout << "默認構造調用" << std::endl;
}
~MoveClass()
{
std::cout << "析構函數調用" << std::endl;
if (!p)
delete p;
}
MoveClass(MoveClass& tmp)
{
}
MoveClass(MoveClass&& tmp)
{
std::cout << "移動構造函數調用" << std::endl;
this->p = tmp.p;
tmp.p = nullptr;
}
MoveClass& operator=(MoveClass&& tmp)
{
std::cout << "移動構造函數調用" << std::endl;
this->p = tmp.p;
tmp.p = nullptr;
}
};
MoveClass MoveClassTest(MoveClass d)
{
return MoveClass();
}
int main()
{
MoveClass cc;
//好 接下來我們不再想使用c了 但是堆區的資源我們并不想拷貝 那么使用如下構造方式
MoveClass d(std::move(cc));
system("pause");
}
移動前數據如下圖所示:
移動后數據如下圖所示:
程序輸出結果:
為什么我們需要move semantic
設想一個場景 我們在一個作用域申請了一個超級大的string 如下圖所示
#include <iostream>
#include <string.h>
void test1(std::string s)
{
std::cout << "test1:" << s.c_str()<<std::endl;;
}
void test()
{
std::string s = "超級大的string";
test1(s);
std::cout <<"test:"<< s.c_str() << std::endl;
return;
}
int main()
{
test();
system("pause");
}
運行結果如下:
你們就要說了 有啥用啊 但是只要你懂一點c++ 你就會知道 在test中的s我們是不需要了的 也就是我們在test是不想再繼續使用s的 但是在我們調用test1的時候 我們又重新拷貝了s一份 那么性能是不是就浪費了呢?如果這個string超級大 你的程序是不是就很垃呢
我們只需要簡簡單單的加一個std::move 他就不是拷貝 而只是單純的移動指針 如下
#include <iostream>
#include <string.h>
void test1(std::string s)
{
std::cout << "test1:" << s.c_str()<<std::endl;;
}
void test()
{
std::string s = "超級大的string";
test1(std::move(s));
std::cout <<"test:"<< s.c_str() << std::endl;
return;
}
int main()
{
test();
system("pause");
}
運行結果如下:
這就是他最最最本質的作用 一個東西是左值時 你仍然想要他去觸發移動構造記住 其他時候你并不需要去考慮 因為編譯器有優化懂嗎 不要嘗試自己去干擾編譯器的優化 除非你真的非常非常非常清楚你自己正在干什么
原文鏈接:https://blog.csdn.net/qq_16401691/article/details/126424125
相關推薦
- 2022-03-25 .NET微服務架構CI/CD鏡像自動分發_實用技巧
- 2022-09-16 Numpy中的shape、reshape函數的區別_python
- 2023-11-23 python獲取文件夾內所有文件并改名
- 2024-01-14 三種線程安全的List
- 2022-07-12 Docker-swarm快速搭建redis集群的方法步驟_docker
- 2022-02-04 sql語句:and與or的優先級
- 2023-03-02 Conan中的C/C++的依賴管理_C 語言
- 2022-05-23 C++的繼承特性你了解嗎_C 語言
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支