91欧美超碰AV自拍|国产成年人性爱视频免费看|亚洲 日韩 欧美一厂二区入|人人看人人爽人人操aV|丝袜美腿视频一区二区在线看|人人操人人爽人人爱|婷婷五月天超碰|97色色欧美亚州A√|另类A√无码精品一级av|欧美特级日韩特级

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

Modern C++ 有哪些能真正提升開發(fā)效率的語(yǔ)法糖

Linux愛好者 ? 來(lái)源:程序員小方 ? 作者: 張小方 ? 2021-11-09 11:00 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

我們說(shuō)的 Modern C++,一般指的是 C++11 及以后的標(biāo)準(zhǔn),從 C++ 11 開始,Modern C++ 引入了大量的實(shí)用的特性,主要是兩大方面,學(xué)習(xí)的時(shí)候也可以從這兩大方面學(xué)習(xí):

  1. 增強(qiáng)或者改善的語(yǔ)法特性;

  2. 新增的或者改善的 STL 庫(kù)。

我們來(lái)看幾個(gè)具體的案例:

案例 1:統(tǒng)一的類成員初始化語(yǔ)法與 std::initializer_list

在 C++98/03 中,假設(shè)我們要初始化一個(gè)類數(shù)組類型的成員(例如常用的清零操作),我們需要這么寫:

classA
{
public:
A()
{
//初始化arr
arr[0]=0;
arr[1]=0;
arr[2]=0;
arr[3]=0;
}

public:
intarr[4];
};

假設(shè)數(shù)組 arr 較長(zhǎng),我們可以使用循環(huán)或者借助 memset 函數(shù)去初始化,代碼如下:

classA
{
public:
A()
{
//使用循環(huán)初始化arr
for(inti=0;iA()
{
//使用memset初始化arr
memset(arr,0,sizeof(arr));
}

public:
intarr[4];
};

但是,我們知道,在 C++98/08 中我們可以直接通過賦值操作來(lái)初始化一個(gè)數(shù)組的:

intarr[4]={0};

但是對(duì)于作為類的成員變量的數(shù)組元素,C++98/03 是不允許我們這么做的。到 C++11 中全部放開并統(tǒng)一了,在 C++11 中我們也可以使用這樣的語(yǔ)法是初始化數(shù)組:

classA
{
public:
//在C++11中可以使用大括號(hào)語(yǔ)法初始化數(shù)組類型的成員變量
A():arr{0}
{
}

public:
intarr[4];
};

如果你有興趣,我們可以更進(jìn)一步:在 C++ 98/03 標(biāo)準(zhǔn)中,對(duì)類的成員必須使用 static const 修飾,而且類型必須是整型 (包括 bool、 char、 int、 long 等),這樣才能使用這種初始化語(yǔ)法:

//C++98/03在類定義處初始化成員變量
classA
{
public:
//T的類型必須是整型,且必須使用staticconst修飾
staticconstTt=某個(gè)整型值;
};

在 C++11 標(biāo)準(zhǔn)中就沒有這種限制了,我們可以使用花括號(hào)(即{})對(duì)任意類型的變 量進(jìn)行初始化,而且不用是 static 類型:

//C++11在類定義處初始化成員變量
classA
{
public:
//有沒有一種Java初始化類成員變量的即視感^_^
boolma{true};
intmb{2019};
std::stringmc{"helloworld"};
};

當(dāng)然,在實(shí)際開發(fā)中,建議還是將這些成員變量的初始化統(tǒng)一寫到構(gòu)造函數(shù)的初始化列表中,方便閱讀和維護(hù)代碼。

案例 2:注解標(biāo)簽

C++ 14 引入了[[deprecated]]標(biāo)簽來(lái)表示一個(gè)函數(shù)或者類型等已被棄用,在使用這些被棄用的函數(shù)或者類型并編譯時(shí), 編譯器會(huì)給出相應(yīng)的警告, 有的編譯器直接生成編譯錯(cuò)誤:

[[deprecated]]voidfuncX();

這個(gè)標(biāo)簽在實(shí)際開發(fā)中非常有用,尤其在設(shè)計(jì)一些庫(kù)代碼時(shí),如果庫(kù)作者希望某個(gè)函數(shù)或者類型不想再被用戶使用,則可以使用該標(biāo)注標(biāo)記。當(dāng)然,我們也可以使用如下語(yǔ)法給出編譯時(shí)的具體警告或者出錯(cuò)信息:

[[deprecated("usefunYinstead")]]voidfuncX();

有如下代碼:

#include
[[deprecated("usefuncYinstead")]]voidfuncX()
{
//實(shí)現(xiàn)省略
}

intmain()
{
funcX();
return0;
}

若在 main 函數(shù)中調(diào)用被標(biāo)記為 deprecated 的函數(shù) funcX,則在 gcc/g++7.3 中編譯時(shí)會(huì)得到如下警告信息:

[root@myaliyuntestmybook]#g++-g-otest_attributestest_attributes.cpp
test_attributes.cpp:Infunction‘intmain()’:
test_attributes.cpp11:warning:‘voidfuncX()’isdeprecated:usefuncYinstead
[-Wdeprecated-declarations]
funcX();
^
test_attributes.cpp42:note:declaredhere
[[deprecated("usefuncYinstead")]]voidfuncX()

Java 開發(fā)者對(duì)這個(gè)標(biāo)注應(yīng)該再熟悉不過了。在 Java 中使用@Deprecated 標(biāo)注可以達(dá)到同樣的效果,這大概是 C++標(biāo)準(zhǔn)委員“拖欠”廣大 C++開發(fā)者太久的一個(gè)特性吧。

C++ 17 提供了三個(gè)實(shí)用注解:[[fallthrough]]、[[nodiscard]]和[[maybe_unused]],這里 逐一介紹它們的用法。[[fallthrough]]用于 switch-case 語(yǔ)句中,在某個(gè) case 分支執(zhí)行完畢后如果沒有 break 語(yǔ)句,則編譯器可能會(huì)給出一條警告。但有時(shí)這可能是開發(fā)者有意為之的。為了讓編譯器明確知道開發(fā)者的意圖,可以在需要某個(gè) case 分支被“貫穿”的地方(上一個(gè) case 沒有break 語(yǔ)句)顯式設(shè)置 [[fallthrough]] 標(biāo)記。代碼示例如下:

switch(type)
{
case1:
func1();
//這個(gè)位置缺少break語(yǔ)句,且沒有fallthrough標(biāo)注,
//可能是一個(gè)邏輯錯(cuò)誤,在編譯時(shí)編譯器可能會(huì)給出警告,以提醒修改

case2:
func2();
//這里也缺少break語(yǔ)句,但是使用了fallthrough標(biāo)注,
//說(shuō)明是開發(fā)者有意為之的,編譯器不會(huì)給出任何警告
[[fallthrough]];

case3:
func3();
}

注意:在 gcc/g++中, [[fallthrough]] 后面的分號(hào)不是必需的,在 Visual Studio 中必須加上分號(hào),否則無(wú)法編譯通過。

熟悉 Golang 的讀者,可能對(duì) fallthrough 這一語(yǔ)法特性非常熟悉, Golang 中在 switch-case 后加上 fallthrough,是一個(gè)常用的告訴編譯器意圖的語(yǔ)法規(guī)則。代碼示例如下:

//以下是Golang語(yǔ)法
s:="abcd"
switchs[3]{
case'a':
fmt.Println("Theintegerwas<=?4")
fallthrough

case'b':
fmt.Println("Theintegerwas<=?5")
fallthrough

case'c':
fmt.Println("Theintegerwas<=?6")

default:
fmt.Println("defaultcase")
}

[[nodiscard]]一般用于修飾函數(shù),告訴函數(shù)調(diào)用者必須關(guān)注該函數(shù)的返回值(即不能丟棄該函數(shù)的返回值)。如果函數(shù)調(diào)用者未將該函數(shù)的返回值賦值給一個(gè)變量,則編譯器會(huì)給出一個(gè)警告。例如,假設(shè)有一個(gè)網(wǎng)絡(luò)連接函數(shù) connect,我們通過返回值明確說(shuō)明了連接是否建立成功,則為了防止調(diào)用者在使用時(shí)直接將該值丟棄,我們可以將該函數(shù)使用[[nodiscard]]標(biāo)記:

[[nodiscard]]intconnect(constchar*address,shortport)
{
//實(shí)現(xiàn)省略
}

intmain()
{
//忽略了connect函數(shù)的返回值,編譯器會(huì)給出一個(gè)警告
connect("127.0.0.1",8888);
return0;
}

在 C++ 20 中,對(duì)于諸如 operator new()、 std::allocate()等庫(kù)函數(shù)均使用了 [[nodiscard]] 進(jìn)行標(biāo)記,以強(qiáng)調(diào)必須使用這些函數(shù)的返回值。再來(lái)看另外一個(gè)標(biāo)記。在通常情況下,編譯器會(huì)對(duì)程序代碼中未使用的函數(shù)或變量給出警告,另一些編譯器干脆不允許通過編譯。在 C++ 17 之前,程序員為了消除這些未使用的變量帶來(lái)的編譯警告或者錯(cuò)誤,要么修改編譯器的警告選項(xiàng)設(shè)置,要么定義一個(gè)類似于 UNREFERENCED_PARAMETER 的宏來(lái)顯式調(diào)用這些未使用的變量一次,以消除編譯警告或錯(cuò)誤:

#defineUNREFERENCED_PARAMETER(x)x

intAPIENTRYwWinMain(HINSTANCEhInstance,HINSTANCEhPrevInstance,LPWSTRlpCmdLine,intnCmdShow)
{
//C++17之前為了消除編譯器對(duì)未使用的變量hPrevInstance、lpCmdLine給出的警告,我們可以這么做
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
//無(wú)關(guān)代碼省略
}

以上代碼節(jié)選自一個(gè)標(biāo)準(zhǔn) Win32 程序的結(jié)構(gòu),其中的函數(shù)參數(shù) hPrevInstance 和 lpCmdLine 一般不會(huì)被用到,編譯器會(huì)給出警告。為了消除這類警告,這里定義了一個(gè)宏 UNREFERENCED_PARAMETER 并進(jìn)行調(diào)用,造成這兩個(gè)參數(shù)被使用的假象。C++17 有了 [[maybe_unused]] 注解之后,我們就再也不需要這類宏來(lái)“欺騙”編譯器了。以上代碼使用該注解后可以修改如下:

intAPIENTRYwWinMain(HINSTANCEhInstance,
[[maybe_unused]]HINSTANCEhPrevInstance,
[[maybe_unused]]LPWSTRlpCmdLine,
intnCmdShow)
{
//無(wú)關(guān)代碼省略
}

案例 3:final、 override 關(guān)鍵字和 =default、 =delete 語(yǔ)法

3.1 final 關(guān)鍵字

在 C++11 之前,我們沒有特別好的方法阻止一個(gè)類被其他類繼承,到了 C++11 有了 final 關(guān)鍵字我們就可以做到了。final 關(guān)鍵字修飾一個(gè)類,這個(gè)類將不允許被繼承,這在其他語(yǔ)言(如 Java)中早就實(shí)現(xiàn)了。在 C++ 11 中, final 關(guān)鍵字要寫在類名的后面,這在其他語(yǔ)言中是寫在 class 關(guān)鍵字前面的。示例如下:

classAfinal
{
};

classB:A
{
};

由于類 A 被聲明成 final, B 繼承 A, 所以編譯器會(huì)報(bào)如下錯(cuò)誤提示類 A 不能被繼承:

errorC3246:'B':cannotinheritfrom'A'asithasbeendeclaredas'final'

3.2 override 關(guān)鍵字

C++98/03 語(yǔ)法規(guī)定,在父類中加了 virtual 關(guān)鍵字的方法可以被子類重寫,子類重寫該方法時(shí)可以加或不加 virtual 關(guān)鍵字,例如下面這樣:

classA
{
protected:
virtualvoidfunc(inta,intb)
{
}
};

classB:A
{
protected:
virtualvoidfunc(inta,intb)
{
}
};

classC:B
{
protected:
voidfunc(inta,intb)
{
}
};

這種寬松的規(guī)定可能會(huì)帶來(lái)以下兩個(gè)問題。

  • 當(dāng)我們閱讀代碼時(shí),無(wú)論子類重寫的方法是否添加了 virtual 關(guān)鍵字,我們都無(wú)法 直觀地確定該方法是否是重寫的父類方法。

  • 如果我們?cè)谧宇愔胁恍⌒膶戝e(cuò)了需要重寫的方法的函數(shù)簽名(可能是參數(shù)類型、 個(gè)數(shù)或返回值類型),這個(gè)方法就會(huì)變成一個(gè)獨(dú)立的方法,這可能會(huì)違背我們重寫 父類某個(gè)方法的初衷,而編譯器在編譯時(shí)并不會(huì)檢查到這個(gè)錯(cuò)誤。

為了解決以上兩個(gè)問題, C++11 引進(jìn)了 override 關(guān)鍵字,其實(shí) override 關(guān)鍵字并不是新語(yǔ)法,在 Java 等其他編程語(yǔ)言中早就支持。類方法被 override 關(guān)鍵字修飾,表明該方法重寫了父類的同名方法,加了該關(guān)鍵字后,編譯器會(huì)在編譯階段做相應(yīng)的檢查,如果其父類不存在相同簽名格式的類方法,編譯器就會(huì)給出相應(yīng)的錯(cuò)誤提示。情形一,父類不存在,子類標(biāo)記了 override 的方法:

classA
{
};

classB:A
{
protected:
voidfunc(intk,intd)override
{
}
};

由于在父類 A 中沒有 func 方法,所以編譯器會(huì)提示錯(cuò)誤:

errorC3668:'B::func':methodwithoverridespecifier'override'didnotoverride
anybaseclassmethods

情形二,父類存在,子類標(biāo)記了 override 的方法,但函數(shù)簽名不一致:

classA
{
protected:
virtualintfunc(intk,intd)
{
return0;
}
};

classB:A
{
protected:
virtualvoidfunc(intk,intd)override
{
}
};

上述代碼編譯器會(huì)報(bào)同樣的錯(cuò)誤。正確的代碼如下:

classA
{
protected:
virtualvoidfunc(intk,intd)
{
}
};

classB:A
{
protected:
virtualvoidfunc(intk,intd)override
{
}
};

3.3 default 語(yǔ)法

如果一個(gè) C++類沒有顯式給出構(gòu)造函數(shù)、析構(gòu)函數(shù)、拷貝構(gòu)造函數(shù)、 operator= 這幾類函數(shù)的實(shí)現(xiàn),則在需要它們時(shí),編譯器會(huì)自動(dòng)生成;或者,在給出這些函數(shù)的聲明時(shí),如果沒有給出其實(shí)現(xiàn),則編譯器在鏈接時(shí)會(huì)報(bào)錯(cuò)。如果使用=default 標(biāo)記這類函數(shù),則編譯器會(huì)給出默認(rèn)的實(shí)現(xiàn)。來(lái)看一個(gè)例子:

classA
{
};

intmain()
{
Aa;
return0;
}

這樣的代碼是可以編譯通過的,因?yàn)榫幾g器默認(rèn)生成 A 的一個(gè)無(wú)參構(gòu)造函數(shù),假設(shè)我們現(xiàn)在向 A 提供一個(gè)有參構(gòu)造函數(shù):

classA
{
public:
A(inti)
{
}
};

intmain()
{
Aa;
return0;
}

這時(shí),編譯器就不會(huì)自動(dòng)生成默認(rèn)的無(wú)參構(gòu)造函數(shù)了,這段代碼會(huì)編譯出錯(cuò),提示 A 沒有合適的無(wú)參構(gòu)造函數(shù):

errorC2512:'A':noappropriatedefaultconstructoravailable

我們這時(shí)可以手動(dòng)為 A 加上無(wú)參構(gòu)造函數(shù), 也可以使用=default 語(yǔ)法強(qiáng)行讓編譯器自己生成:

classA
{
public:
A()=default;
A(inti)
{
}
};

intmain()
{
Aa;
return0;
}

=default 最大的作用可能是在開發(fā)中簡(jiǎn)化了構(gòu)造函數(shù)中沒有實(shí)際初始化代碼的寫法,尤其是聲明和實(shí)現(xiàn)分別屬于.h 和.cpp 文件。例如,對(duì)于類 A,其頭文件為 a.h,其實(shí)現(xiàn)文件為 a.cpp,則正常情況下我們需要在 a.cpp 文件中寫其構(gòu)造函數(shù)和析構(gòu)函數(shù)的實(shí)現(xiàn)(可能沒有實(shí)際的構(gòu)造和析構(gòu)邏輯):

//a.h
classA
{
public:
A();
~A();
};

//a.cpp
#include"a.h"

A::A()
{
}

A::~A()
{
}

可以發(fā)現(xiàn),即使在 A 的構(gòu)造函數(shù)和析構(gòu)函數(shù)中什么邏輯也沒有,我們還是不得不在 a.cpp 中寫上構(gòu)造函數(shù)和析構(gòu)函數(shù)的實(shí)現(xiàn)。有了=default 關(guān)鍵字,我們就可以在 a.h 中直接寫成:

//a.h
classA
{
public:
A()=default;
~A()=default;
};

//a.cpp
#include"a.h"
//在cpp文件中就不用再寫A的構(gòu)造函數(shù)和析構(gòu)函數(shù)的實(shí)現(xiàn)了

3.4 =delete 語(yǔ)法

既然有強(qiáng)制讓編譯器生成構(gòu)造函數(shù)、析構(gòu)函數(shù)、拷貝構(gòu)造函數(shù)、 operator=的語(yǔ)法,那么也應(yīng)該有禁止編譯器生成這些函數(shù)的語(yǔ)法,沒錯(cuò),就是 =delete。在 C++ 98/03 規(guī)范中, 如果我們想讓一個(gè)類不能被拷貝(即不能調(diào)用其拷貝構(gòu)造函數(shù)),則可以將其拷貝構(gòu)造函數(shù)和 operator=函數(shù)定義成 private 的:

classA
{
public:
A()=default;
~A()=default;

private:
A(constA&a)
{
}

A&operator=(constA&a)
{
}
};

intmain()
{
Aa1;
Aa2(a1);
Aa3;
a3=a1;
return0;
}

通過以上代碼利用 a1 構(gòu)造 a2 時(shí),編譯器會(huì)提示錯(cuò)誤:

errorC2248:'A::A':cannotaccessprivatememberdeclaredinclass'A'
errorC2248:'A::operator=':cannotaccessprivatememberdeclaredinclass'A'

我們利用這種方式間接實(shí)現(xiàn)了一個(gè)類不能被拷貝的功能,這也是繼承自 boost::noncopyable 的類不能被拷貝的實(shí)現(xiàn)原理?,F(xiàn)在有了=delete語(yǔ)法,我們直接使用該語(yǔ)法禁止編譯器生成這兩個(gè)函數(shù)即可:

classA
{
public:
A()=default;
~A()=default;
public:
A(constA&a)=delete;
A&operator=(constA&a)=delete;
};

intmain()
{
Aa1;
//Aa2(a1);
Aa3;
//a3=a1;
return0;
}

一般在一些工具類中, 我們不需要用到構(gòu)造函數(shù)、 析構(gòu)函數(shù)、 拷貝構(gòu)造函數(shù)、 operator= 這 4 個(gè)函數(shù),為了防止編譯器自己生成,同時(shí)為了減小生成的可執(zhí)行文件的體積,建議使用=delete 語(yǔ)法禁止編譯器為這 4 個(gè)函數(shù)生成默認(rèn)的實(shí)現(xiàn)代碼,例如:

//這是一個(gè)字符轉(zhuǎn)碼工具類
classEncodeUtil
{
public:
staticstd::wstringAnsiiToUnicode(conststd::string&strAnsii);
staticstd::stringUnicodeToAnsii(conststd::wstring&strUnicode);
staticstd::stringAnsiiToUtf8(conststd::string&strAnsii);
staticstd::stringUtf8ToAnsii(conststd::string&strUtf8);
staticstd::stringUnicodeToUtf8(conststd::wstring&strUnicode);
staticstd::wstringUtf8ToUnicode(conststd::string&strUtf8);

private:
EncodeUtil()=delete;
~EncodeUtil()=delete;
EncodeUtil(constEncodeUtil&rhs)=delete;
EncodeUtil&operator=(constEncodeUtil&rhs)=delete;
};

案例 4:對(duì)多線程的支持

我們來(lái)看一個(gè)稍微復(fù)雜一點(diǎn)的例子。在 C++11 之前,由于 C++98/03 本身缺乏對(duì)線程和線程同步原語(yǔ)的支持,我們要寫一個(gè)生產(chǎn)者消費(fèi)者邏輯要這么寫。在 Windows 上:

/**
*RecvMsgTask.h
*/
classCRecvMsgTask:publicCThreadPoolTask
{
public:
CRecvMsgTask(void);
~CRecvMsgTask(void);

public:
virtualintRun();
virtualintStop();
virtualvoidTaskFinish();

BOOLAddMsgData(CBuffer*lpMsgData);

private:
BOOLHandleMsg(CBuffer*lpMsg);

private:
HANDLEm_hEvent;
CRITICAL_SECTIONm_csItem;
HANDLEm_hSemaphore;
std::vectorm_arrItem;
};

/**
*RecvMsgTask.cpp
*/
CRecvMsgTask::CRecvMsgTask(void)
{
::InitializeCriticalSection(&m_csItem);
m_hSemaphore=::CreateSemaphore(NULL,0,0x7FFFFFFF,NULL);
m_hEvent=::CreateEvent(NULL,TRUE,FALSE,NULL);
}

CRecvMsgTask::~CRecvMsgTask(void)
{
::DeleteCriticalSection(&m_csItem);

if(m_hSemaphore!=NULL)
{
::CloseHandle(m_hSemaphore);
m_hSemaphore=NULL;
}

if(m_hEvent!=NULL)
{
::CloseHandle(m_hEvent);
m_hEvent=NULL;
}
}

intCRecvMsgTask::Run()
{
HANDLEhWaitEvent[2];
DWORDdwIndex;
CBuffer*lpMsg;

hWaitEvent[0]=m_hEvent;
hWaitEvent[1]=m_hSemaphore;

while(1)
{
dwIndex=::WaitForMultipleObjects(2,hWaitEvent,FALSE,INFINITE);

if(dwIndex==WAIT_OBJECT_0)
break;

lpMsg=NULL;

::EnterCriticalSection(&m_csItem);
if(m_arrItem.size()>0)
{
//消費(fèi)者從隊(duì)列m_arrItem中取出任務(wù)執(zhí)行
lpMsg=m_arrItem[0];
m_arrItem.erase(m_arrItem.begin()+0);
}
::LeaveCriticalSection(&m_csItem);

if(NULL==lpMsg)
continue;

//處理任務(wù)
HandleMsg(lpMsg);

deletelpMsg;
}

return0;
}

intCRecvMsgTask::Stop()
{
m_HttpClient.SetCancalEvent();
::SetEvent(m_hEvent);
return0;
}

voidCRecvMsgTask::TaskFinish()
{
}

//生產(chǎn)者調(diào)用這個(gè)方法將Task放入隊(duì)列m_arrItem中
BOOLCRecvMsgTask::AddMsgData(CBuffer*lpMsgData)
{
if(NULL==lpMsgData)
returnFALSE;

::EnterCriticalSection(&m_csItem);
m_arrItem.push_back(lpMsgData);
::LeaveCriticalSection(&m_csItem);

::ReleaseSemaphore(m_hSemaphore,1,NULL);

returnTRUE;
}

Linux 下:

#include
#include
#include
#include
#include
#include

classTask
{
public:
Task(inttaskID)
{
this->taskID=taskID;
}

voiddoTask()
{
std::cout<"handleatask,taskID:"<",threadID:"<tasks;
pthread_cond_tmycv;

void*consumer_thread(void*param)
{
Task*pTask=NULL;
while(true)
{
pthread_mutex_lock(&mymutex);
while(tasks.empty())
{
//如果獲得了互斥鎖,但是條件不合適的話,pthread_cond_wait會(huì)釋放鎖,不往下執(zhí)行。
//當(dāng)發(fā)生變化后,條件合適,pthread_cond_wait將直接獲得鎖。
pthread_cond_wait(&mycv,&mymutex);
}

pTask=tasks.front();
tasks.pop_front();

pthread_mutex_unlock(&mymutex);

if(pTask==NULL)
continue;

pTask->doTask();
deletepTask;
pTask=NULL;
}

returnNULL;
}

void*producer_thread(void*param)
{
inttaskID=0;
Task*pTask=NULL;

while(true)
{
pTask=newTask(taskID);

pthread_mutex_lock(&mymutex);
tasks.push_back(pTask);
std::cout<"produceatask,taskID:"<",threadID:"<returnNULL;
}

intmain()
{
pthread_mutex_init(&mymutex,NULL);
pthread_cond_init(&mycv,NULL);

//創(chuàng)建5個(gè)消費(fèi)者線程
pthread_tconsumerThreadID[5];
for(inti=0;ifor(inti=0;ireturn0;
}

怎么樣?上述代碼如果對(duì)于新手來(lái)說(shuō),望而卻步。為了實(shí)現(xiàn)這樣的功能在 Windows 上你需要掌握線程如何創(chuàng)建、線程同步對(duì)象 CriticalSection、Event、Semaphore、WaitForSingleObject/WaitForMultipleObjects 等操作系統(tǒng)對(duì)象和 API。

在 Linux 上需要掌握線程創(chuàng)建,你需要了解線程創(chuàng)建、互斥體、條件變量。對(duì)于需要支持多個(gè)平臺(tái)的開發(fā),需要開發(fā)者同時(shí)熟悉上述原理并編寫多套適用不同平臺(tái)的代碼。C++11 的線程庫(kù)改變了這個(gè)現(xiàn)狀,現(xiàn)在你只需要掌握 std::thread、std::mutex、std::condition_variable 少數(shù)幾個(gè)線程同步對(duì)象即可,同時(shí)使用這些對(duì)象編寫出來(lái)的代碼也可以跨平臺(tái)。示例如下:

#include
#include
#include
#include
#include

classTask
{
public:
Task(inttaskID)
{
this->taskID=taskID;
}

voiddoTask()
{
std::cout<"handleatask,taskID:"<",threadID:"<tasks;
std::condition_variablemycv;

void*consumer_thread()
{
Task*pTask=NULL;
while(true)
{
std::unique_lockguard(mymutex);
while(tasks.empty())
{
//如果獲得了互斥鎖,但是條件不合適的話,pthread_cond_wait會(huì)釋放鎖,不往下執(zhí)行。
//當(dāng)發(fā)生變化后,條件合適,pthread_cond_wait將直接獲得鎖。
mycv.wait(guard);
}

pTask=tasks.front();
tasks.pop_front();

if(pTask==NULL)
continue;

pTask->doTask();
deletepTask;
pTask=NULL;
}

returnNULL;
}

void*producer_thread()
{
inttaskID=0;
Task*pTask=NULL;

while(true)
{
pTask=newTask(taskID);

//使用括號(hào)減小guard鎖的作用范圍
{
std::lock_guardguard(mymutex);
tasks.push_back(pTask);
std::cout<"produceatask,taskID:"<",threadID:"<returnNULL;
}

intmain()
{
//創(chuàng)建5個(gè)消費(fèi)者線程
std::threadconsumer1(consumer_thread);
std::threadconsumer2(consumer_thread);
std::threadconsumer3(consumer_thread);
std::threadconsumer4(consumer_thread);
std::threadconsumer5(consumer_thread);

//創(chuàng)建一個(gè)生產(chǎn)者線程
std::threadproducer(producer_thread);

producer.join();
consumer1.join();
consumer2.join();
consumer3.join();
consumer4.join();
consumer5.join();

return0;
}

感覺如何?代碼既簡(jiǎn)潔又統(tǒng)一。這就是 C++11 之后使用 Modern C++ 開發(fā)的效率!C++11 之后的 C++ 更像一門新的語(yǔ)言。當(dāng) C++11 的編譯器發(fā)布之后(Visual Studio 2013、g++4.8),我第一時(shí)間更新了我的編譯器,同時(shí)把我們的項(xiàng)目使用了 C++11 特性進(jìn)行了改造。當(dāng)然,例子還有很多,限于文章篇幅,這里就列舉 4 個(gè)案例。

當(dāng)然,Modern C++ 已經(jīng)成為業(yè)界開發(fā)的主流,你應(yīng)該歡迎它、擁抱它、熟悉它、使用它。

編輯:jq
聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • Linux
    +關(guān)注

    關(guān)注

    88

    文章

    11760

    瀏覽量

    219040
  • API
    API
    +關(guān)注

    關(guān)注

    2

    文章

    2372

    瀏覽量

    66789
  • C++
    C++
    +關(guān)注

    關(guān)注

    22

    文章

    2124

    瀏覽量

    77121
  • 代碼
    +關(guān)注

    關(guān)注

    30

    文章

    4968

    瀏覽量

    73976

原文標(biāo)題:Modern C++ 有哪些能真正提升開發(fā)效率的語(yǔ)法糖?

文章出處:【微信號(hào):LinuxHub,微信公眾號(hào):Linux愛好者】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    甜蜜升級(jí):疆鴻智能DEVICENET無(wú)縫轉(zhuǎn)換ETHERCAT賦真空熬智控

    甜蜜升級(jí):疆鴻智能DEVICENET無(wú)縫轉(zhuǎn)換ETHERCAT賦真空熬智控 在工業(yè)自動(dòng)化系統(tǒng)中,不同設(shè)備與控制器之間常因協(xié)議標(biāo)準(zhǔn)不一致而形成信息孤島,協(xié)議轉(zhuǎn)換網(wǎng)關(guān)成為實(shí)現(xiàn)互聯(lián)互通的關(guān)鍵樞紐。本文以
    的頭像 發(fā)表于 01-21 13:56 ?169次閱讀

    通過vivado HLS設(shè)計(jì)一個(gè)FIR低通濾波器

    Vivado HLS是一款強(qiáng)大的高層次綜合工具,可將C/C++代碼轉(zhuǎn)換為硬件描述語(yǔ)言(HDL),顯著提升FPGA開發(fā)效率。
    的頭像 發(fā)表于 01-20 16:19 ?312次閱讀
    通過vivado HLS設(shè)計(jì)一個(gè)FIR低通濾波器

    C語(yǔ)言與C++的區(qū)別及聯(lián)系

    缺點(diǎn):性能比面向過程低。 二、具體語(yǔ)言上的區(qū)別 1、關(guān)鍵字的不同 C語(yǔ)言32個(gè)關(guān)鍵字;C++63個(gè)關(guān)鍵字。 2、后綴名不同 C
    發(fā)表于 12-24 07:23

    CC++之間的聯(lián)系

    ,后來(lái)才逐漸演變?yōu)橐环N成熟的面向?qū)ο缶幊陶Z(yǔ)言。 總之,C語(yǔ)言和C++雖然很多共同之處,但在編程范式、安全性、抽象層次等方面存在顯著差異。開發(fā)者可以根據(jù)項(xiàng)目需求選擇合適的語(yǔ)言,
    發(fā)表于 12-11 06:51

    C語(yǔ)言和C++之間的區(qū)別是什么

    (STL),包含多種容器(如vector、list、map等)、算法以及迭代器,極大地提高了開發(fā)效率和代碼復(fù)用性。 而C語(yǔ)言的標(biāo)準(zhǔn)庫(kù)相對(duì)較小,雖然也提供了基本的數(shù)據(jù)結(jié)構(gòu)(如數(shù)組、鏈表等)和算法的支持,但不
    發(fā)表于 12-11 06:23

    C++程序異常的處理機(jī)制

    1、什么是異常處理? 經(jīng)驗(yàn)的朋友應(yīng)該知道,在正常的CC++編程過程中難免會(huì)碰到程序不按照原本設(shè)計(jì)運(yùn)行的情況。 最常見的除法分母為零,數(shù)組越界,內(nèi)存分配失效、打開相應(yīng)文件失敗等等
    發(fā)表于 12-02 07:12

    PLC熏爐物聯(lián)網(wǎng)遠(yuǎn)程監(jiān)控系統(tǒng)方案

    食品加工行業(yè)正朝著智能化、自動(dòng)化、數(shù)字化方向轉(zhuǎn)型,企業(yè)需要通過物聯(lián)網(wǎng)技術(shù)實(shí)現(xiàn)設(shè)備互聯(lián)、數(shù)據(jù)互通,提升生產(chǎn)過程的透明度和可控性。 熏爐作為重要的生產(chǎn)設(shè)備,廣泛應(yīng)用于肉制品、豆制品等食品的熏加工環(huán)節(jié)
    的頭像 發(fā)表于 10-17 17:23 ?483次閱讀

    Perforce QAC產(chǎn)品簡(jiǎn)介:面向C/C++的靜態(tài)代碼分析工具(已通過SO 26262認(rèn)證)

    Perforce QAC專為C/C++開發(fā)者打造,支持多種編碼規(guī)范、功能安全標(biāo)準(zhǔn)(ISO 26262)等,廣泛用于汽車、醫(yī)療、嵌入式開發(fā)領(lǐng)域,可幫助快速識(shí)別關(guān)鍵缺陷、
    的頭像 發(fā)表于 07-10 15:57 ?1274次閱讀
    Perforce QAC產(chǎn)品簡(jiǎn)介:面向<b class='flag-5'>C</b>/<b class='flag-5'>C++</b>的靜態(tài)代碼分析工具(已通過SO 26262認(rèn)證)

    DevEco CodeGenie 鴻蒙AI 輔助編程初次使用

    :基于 DeepSeek-R1 智能體,解答 HarmonyOS 開發(fā)問題(如 ArkTS 語(yǔ)法、多線程實(shí)現(xiàn)等)。 代碼生成與續(xù)寫 :支持 ArkTS/C++ 代碼片段生成,可根據(jù)自然語(yǔ)言描述或代碼
    的頭像 發(fā)表于 06-26 08:48 ?926次閱讀

    交流充電樁負(fù)載提升技術(shù)

    隨著電動(dòng)汽車普及率提升,交流充電樁的效優(yōu)化成為降低運(yùn)營(yíng)成本、減少能源浪費(fèi)的核心課題。負(fù)載提升需從硬件設(shè)計(jì)、拓?fù)鋬?yōu)化、智能控制及熱管理等多維度展開,以下結(jié)合技術(shù)原理與實(shí)踐方案進(jìn)行闡
    發(fā)表于 05-21 14:38

    主流的 MCU 開發(fā)語(yǔ)言為什么是 C 而不是 C++?

    在單片機(jī)的地界兒里,C語(yǔ)言穩(wěn)坐中軍帳,C++想分杯羹?難嘍。咱電子工程師天天跟那針尖大的內(nèi)存空間較勁,C++那些花里胡哨的玩意兒,在這兒真玩不轉(zhuǎn)。先說(shuō)內(nèi)存這道坎兒。您當(dāng)stm32f4的256kRAM
    的頭像 發(fā)表于 05-21 10:33 ?1044次閱讀
    主流的 MCU <b class='flag-5'>開發(fā)</b>語(yǔ)言為什么是 <b class='flag-5'>C</b> 而不是 <b class='flag-5'>C++</b>?

    harmony OS NEXT-雙向數(shù)據(jù)綁定MVVM以及$$語(yǔ)法介紹

    # 鴻蒙Harmony-雙向數(shù)據(jù)綁定MVVM以及$$語(yǔ)法介紹 ## 1.1 雙向數(shù)據(jù)綁定概念 在鴻蒙(HarmonyOS)應(yīng)用開發(fā)中,雙向數(shù)據(jù)改變(或雙向數(shù)據(jù)綁定)是一種讓數(shù)據(jù)·模型和UI組件之間
    的頭像 發(fā)表于 04-29 16:52 ?1251次閱讀

    DevEco Studio AI輔助開發(fā)工具兩大升級(jí)功能 鴻蒙應(yīng)用開發(fā)效率提升

    HarmonyOS應(yīng)用的AI智能輔助開發(fā)助手——CodeGenie,該AI助手深度集成在DevEco Studio中,提供鴻蒙知識(shí)智能問答、鴻蒙ArkTS代碼補(bǔ)全/生成和萬(wàn)卡片生成等功能,提升
    發(fā)表于 04-18 14:43

    小程序開發(fā)必須知道的5個(gè)技巧:提升效率與用戶體驗(yàn)的權(quán)威指南

    精準(zhǔn)定位核心場(chǎng)景。 需求分析:明確目標(biāo)用戶痛點(diǎn),如電商類小程序需優(yōu)先優(yōu)化購(gòu)物車與支付流程,而非復(fù)雜營(yíng)銷工具。 模塊化開發(fā):通過自定義組件封裝高頻功能(如分享按鈕、客服入口),提升代碼復(fù)用率與維護(hù)效率
    發(fā)表于 03-14 14:51

    C++學(xué)到什么程度可以找工作?

    C++學(xué)到什么程度可以找工作?要使用C++找到工作,特別是作為軟件開發(fā)人員或相關(guān)職位,通常需要掌握以下幾個(gè)方面: 1. **語(yǔ)言基礎(chǔ)**:你需要對(duì)C++的核心概念
    發(fā)表于 03-13 10:19