欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C++基本用法實(shí)踐之移動(dòng)語(yǔ)義詳解

 更新時(shí)間:2023年07月17日 11:41:52   作者:寡人正在Coding  
移動(dòng)(move)語(yǔ)義是C++引入了一種新的內(nèi)存優(yōu)化,以避免不必要的拷貝,下面小編就來(lái)和大家簡(jiǎn)單聊聊C++中移動(dòng)語(yǔ)義的相關(guān)使用吧,希望對(duì)大家有所幫助

概述

移動(dòng)

移動(dòng)(move)語(yǔ)義C++引入了一種新的內(nèi)存優(yōu)化,以避免不必要的拷貝。在構(gòu)造或者賦值的時(shí)候,如果實(shí)參是右值(或者左值由std::move轉(zhuǎn)換成右值),便會(huì)匹配移動(dòng)語(yǔ)義的函數(shù)調(diào)用如下述舉例的Str(Str&& obj)。

移動(dòng)語(yǔ)義的本質(zhì)是將資源(內(nèi)存/句柄)轉(zhuǎn)移給另一個(gè)對(duì)象,被轉(zhuǎn)移資源的對(duì)象不應(yīng)再被使用。(這個(gè)概念有點(diǎn)像仙俠小說(shuō)中的奪舍,奪舍成功的人獲取被奪舍的人的身體(資源)),如下面?zhèn)未a:

class Obj
{
	data
	Obj(){
		data = malloc(100)
	}
	// 移動(dòng) (奪舍)
	Obj(Obj&& other){
		data = other.data
		other.data = nullptr
	}
}

右值

右值直觀理解是等號(hào)右邊的值(大概如此,并不準(zhǔn)確),右值的概念指代的東西比較多,大概是指不可尋址的值(也有例外)。我覺(jué)得這個(gè)不必太過(guò)糾結(jié),記住幾個(gè)常見(jiàn)的即可:

  • 臨時(shí)對(duì)象:如函數(shù)返回的臨時(shí)對(duì)象(下面有舉例)
  • 字面量
  • 顯式std::move()轉(zhuǎn)換的值
  • 沒(méi)有捕獲參數(shù)的lambda

C++ 值類(lèi)別表

在 C++11之后,C++根據(jù)

  • 被標(biāo)識(shí):可通過(guò)不同標(biāo)識(shí)符指代同一實(shí)體。(對(duì)象/內(nèi)存)
  • 可移動(dòng):可作為移動(dòng)語(yǔ)義函數(shù)的參數(shù),例如移動(dòng)構(gòu)造,移動(dòng)賦值。

將值分為以下類(lèi)別:

泛左值:被標(biāo)識(shí)

  • 左值:被標(biāo)識(shí)且不可移動(dòng)
  • 將亡值:被標(biāo)識(shí)可移動(dòng)

右值:可移動(dòng)

  • 將亡值:被標(biāo)識(shí)可移動(dòng)
  • 純右值:不被標(biāo)識(shí)且可移動(dòng)

用法舉例

參考測(cè)試項(xiàng)目代碼ModernCppTest/modrenc_rvalueref_stdmove.cpp主要內(nèi)容:

  • 移動(dòng)語(yǔ)義下的構(gòu)造和賦值
  • 移動(dòng)還是拷貝的重載匹配
  • C++ 優(yōu)化臨時(shí)對(duì)象(連加產(chǎn)生的中間臨時(shí)對(duì)象)嘗試調(diào)用移動(dòng)語(yǔ)義
#include "ModernCppTestHeader.h"
#include <string>
using std::string;

namespace n_rvalueref {
	class Str {
	public:
		Str() {
			LOG("無(wú)參構(gòu)造");
			this->str = new string();
		}

		Str(const string& str) {
			LOG("有參構(gòu)造 str = " << str);
			this->str = new string(str);
		}

		Str(const Str& obj) {
			LOG("拷貝構(gòu)造 obj.str = " << *obj.str);
			this->str = new string(*obj.str);
		}

		Str(Str&& obj) noexcept {
			LOG("移動(dòng)構(gòu)造 obj.str = " << *obj.str);
			this->str = std::move(obj.str);
			// 被移動(dòng)的對(duì)象不應(yīng)該再被使用了
			obj.str = nullptr;
		}

		Str& operator=(Str&& v) noexcept {
			LOG("移動(dòng)語(yǔ)義 operator = ");

			if (this != &v) {
				this->str = std::move(v.str);
			}

			return *this;
		}

		Str operator+(const Str& v)
		{
			string s = *this->str + *v.str;
			return Str(s);
		}

		void Log()
		{
			LOG(str);
		}

		string* str;
	};
}

using n_rvalueref::Str;

// 右值引用&移動(dòng)語(yǔ)義
void rvalueref_stdmove_test()
{
	LOG_FUNC();

	LOG_TAG("拷貝構(gòu)造");
	{
		Str t1("A");
		Str t2 = t1;
		LOG_VAR(*t2.str);
	}


	LOG_TAG("移動(dòng)構(gòu)造, 注意被移動(dòng)的對(duì)象t1不應(yīng)再被使用");
	{
		// t1是左值,使用std::move強(qiáng)制轉(zhuǎn)換成右值
		Str t1("A");
		Str t2 = std::move(t1);
		LOG_VAR(*t2.str);
	}


	LOG_TAG("移動(dòng)語(yǔ)義的運(yùn)算符重載,注意運(yùn)算符重載發(fā)生賦值運(yùn)算(這個(gè)例子),而不是構(gòu)造運(yùn)算(上個(gè)例子)");
	{
		Str t1("A");
		Str t2;
		t2 = std::move(t1);
	}


	LOG_TAG("除了上述顯示使用std::move轉(zhuǎn)換,常見(jiàn)的容易忽視的發(fā)生移動(dòng)構(gòu)造場(chǎng)合列舉");
	{
		LOG("---1 連續(xù)加法產(chǎn)生的臨時(shí)對(duì)象,c++會(huì)嘗試使用移動(dòng)語(yǔ)義進(jìn)行優(yōu)化");
		Str t1("A");
		Str t2("B");
		Str t3("C");
		Str t4;
		t4 = t1 + t2 + t3;

		LOG("---2 函數(shù)返回的臨時(shí)對(duì)象,c++會(huì)嘗試使用移動(dòng)語(yǔ)義進(jìn)行優(yōu)化");
		auto f = []() {
			auto s = Str("Hi"); 
			return s; 
		};
		Str t5 = f();

		/*
		- 在容器中插入或刪除元素:比如 std::vector::push_back,如果傳遞給它的是右值,它就會(huì)使用移動(dòng)語(yǔ)義。
		- 在標(biāo)準(zhǔn)庫(kù)算法中:許多標(biāo)準(zhǔn)庫(kù)算法,比如 std::sort,std::partition 等,在進(jìn)行元素交換時(shí)會(huì)使用移動(dòng)語(yǔ)義。
		- 在 std::swap 中:std::swap 會(huì)使用移動(dòng)語(yǔ)義來(lái)交換兩個(gè)對(duì)象。
		*/
	}
}

到此這篇關(guān)于C++基本用法實(shí)踐之移動(dòng)語(yǔ)義詳解的文章就介紹到這了,更多相關(guān)C++移動(dòng)語(yǔ)義內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論