chinese直男口爆体育生外卖, 99久久er热在这里只有精品99, 又色又爽又黄18禁美女裸身无遮挡, gogogo高清免费观看日本电视,私密按摩师高清版在线,人妻视频毛茸茸,91论坛 兴趣闲谈,欧美 亚洲 精品 8区,国产精品久久久久精品免费

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

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

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

關(guān)于提升 C++ 開發(fā)效率你不知道的小技巧

開關(guān)電源芯片 ? 來源:程序員小方 ? 作者:張小方 ? 2021-08-14 09:59 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

我們說的 Modern C++,一般指的是 C++11 及以后的標準,從 C++ 11 開始,Modern C++ 引入了大量的實用的特性,主要是兩大方面,學習的時候也可以從這兩大方面學習:

增強或者改善的語法特性;

新增的或者改善的 STL 庫。

我們來看幾個具體的案例:

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

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

class A

{

public:

A()

{

//初始化arr

arr[0] = 0;

arr[1] = 0;

arr[2] = 0;

arr[3] = 0;

}

public:

int arr[4];

};

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

class A

{

public:

A()

{

//使用循環(huán)初始化arr

for (int i = 0; i 《 4; i++)

arr[i] = 0;

}

public:

int arr[4];

};

class A

{

public:

A()

{

//使用memset初始化arr

memset(arr, 0, sizeof(arr));

}

public:

int arr[4];

};

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

int arr[4] = { 0 };

但是對于作為類的成員變量的數(shù)組元素,C++98/03 是不允許我們這么做的。

到 C++11 中全部放開并統(tǒng)一了,在 C++11 中我們也可以使用這樣的語法是初始化數(shù)組:

class A

{

public:

//在 C++11中可以使用大括號語法初始化數(shù)組類型的成員變量

A() : arr{0}

{

}

public:

int arr[4];

};

如果你有興趣,我們可以更進一步:

在 C++ 98/03 標準中,對類的成員必須使用 static const 修飾,而且類型必須是整型 (包括 bool、 char、 int、 long 等),這樣才能使用這種初始化語法:

//C++98/03 在類定義處初始化成員變量

class A

{

public:

//T 的類型必須是整型,且必須使用 static const 修飾

static const T t = 某個整型值;

};

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

//C++ 11 在類定義處初始化成員變量

class A

{

public:

//有沒有一種Java初始化類成員變量的即視感^ _ ^

bool ma{true};

int mb{2019};

std::string mc{“helloworld”};

};

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

案例 2:注解標簽

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

[[deprecated]] void funcX();

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

[[deprecated(“use funY instead”)]] void funcX();

有如下代碼:

#include 《iostream》

[[deprecated(“use funcY instead”)]] void funcX()

{

//實現(xiàn)省略

}

int main()

{

funcX();

return 0;

}

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

[root@myaliyun testmybook]# g++ -g -o test_attributes test_attributes.cpp

test_attributes.cpp: In function ‘int main()’:

test_attributes.cpp11: warning: ‘void funcX()’ is deprecated: use funcY instead

[-Wdeprecated-declarations]

funcX();

^

test_attributes.cpp42: note: declared here

[[deprecated(“use funcY instead”)]] void funcX()

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

C++ 17 提供了三個實用注解:[[fallthrough]]、 [[nodiscard]] 和 [[maybe_unused]],這里 逐一介紹它們的用法。

[[fallthrough]] 用于 switch-case 語句中,在某個 case 分支執(zhí)行完畢后如果沒有 break 語句,則編譯器可能會給出一條警告。但有時這可能是開發(fā)者有意為之的。為了讓編譯器明確知道開發(fā)者的意圖,可以在需要某個 case 分支被“貫穿”的地方(上一個 case 沒有break 語句)顯式設(shè)置 [[fallthrough]] 標記。代碼示例如下:

switch (type)

{

case 1:

func1();

//這個位置缺少 break 語句,且沒有 fallthrough 標注,

//可能是一個邏輯錯誤,在編譯時編譯器可能會給出警告,以提醒修改

case 2:

func2();

//這里也缺少 break 語句,但是使用了 fallthrough 標注,

//說明是開發(fā)者有意為之的,編譯器不會給出任何警告

[[fallthrough]];

case 3:

func3();

}

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

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

//以下是 Golang 語法

s := “abcd”

switch s[3] {

case ‘a(chǎn)’:

fmt.Println(“The integer was 《= 4”)

fallthrough

case ‘b’:

fmt.Println(“The integer was 《= 5”)

fallthrough

case ‘c’:

fmt.Println(“The integer was 《= 6”)

default:

fmt.Println(“default case”)

}

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

[[nodiscard]] int connect(const char* address, short port)

{

//實現(xiàn)省略

}

int main()

{

//忽略了connect函數(shù)的返回值,編譯器會給出一個警告

connect(“127.0.0.1”, 8888);

return 0;

}

在 C++ 20 中,對于諸如 operator new()、 std::allocate()等庫函數(shù)均使用了 [[nodiscard]] 進行標記,以強調(diào)必須使用這些函數(shù)的返回值。

再來看另外一個標記。

在通常情況下,編譯器會對程序代碼中未使用的函數(shù)或變量給出警告,另一些編譯器干脆不允許通過編譯。在 C++ 17 之前,程序員為了消除這些未使用的變量帶來的編譯警告或者錯誤,要么修改編譯器的警告選項設(shè)置,要么定義一個類似于 UNREFERENCED_PARAMETER 的宏來顯式調(diào)用這些未使用的變量一次,以消除編譯警告或錯誤:

#define UNREFERENCED_PARAMETER(x) x

int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow)

{

//C++17之前為了消除編譯器對未使用的變量hPrevInstance、lpCmdLine給出的警告,我們可以這么做

UNREFERENCED_PARAMETER(hPrevInstance);

UNREFERENCED_PARAMETER(lpCmdLine);

//無關(guān)代碼省略

}

以上代碼節(jié)選自一個標準 Win32 程序的結(jié)構(gòu),其中的函數(shù)參數(shù) hPrevInstance 和 lpCmdLine 一般不會被用到,編譯器會給出警告。為了消除這類警告,這里定義了一個宏 UNREFERENCED_PARAMETER 并進行調(diào)用,造成這兩個參數(shù)被使用的假象。

C++17 有了 [[maybe_unused]] 注解之后,我們就再也不需要這類宏來“欺騙”編譯器了。以上代碼使用該注解后可以修改如下:

int APIENTRY wWinMain(HINSTANCE hInstance,

[[maybe_unused]] HINSTANCE hPrevInstance,

[[maybe_unused]] LPWSTR lpCmdLine,

int nCmdShow)

{

//無關(guān)代碼省略

}

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

3.1 final 關(guān)鍵字

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

class A final

{

};

class B : A

{

};

由于類 A 被聲明成 final, B 繼承 A, 所以編譯器會報如下錯誤提示類 A 不能被繼承:

error C3246: ‘B’ : cannot inherit from ‘A’ as it has been declared as ‘final’

3.2 override 關(guān)鍵字

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

class A

{

protected:

virtual void func(int a, int b)

{

}

};

class B : A

{

protected:

virtual void func(int a, int b)

{

}

};

class C : B

{

protected:

void func(int a, int b)

{

}

};

這種寬松的規(guī)定可能會帶來以下兩個問題。

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

如果我們在子類中不小心寫錯了需要重寫的方法的函數(shù)簽名(可能是參數(shù)類型、 個數(shù)或返回值類型),這個方法就會變成一個獨立的方法,這可能會違背我們重寫 父類某個方法的初衷,而編譯器在編譯時并不會檢查到這個錯誤。

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

情形一,父類不存在,子類標記了 override 的方法:

class A

{

};

class B : A

{

protected:

void func(int k, int d) override

{

}

};

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

error C3668: ‘B::func’ : method with override specifier ‘override’ did not override

any base class methods

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

class A

{

protected:

virtual int func(int k, int d)

{

return 0;

}

};

class B : A

{

protected:

virtual void func(int k, int d) override

{

}

};

上述代碼編譯器會報同樣的錯誤。正確的代碼如下:

class A

{

protected:

virtual void func(int k, int d)

{

}

};

class B : A

{

protected:

virtual void func(int k, int d) override

{

}

};

3.3 default 語法

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

class A

{

};

int main()

{

A a;

return 0;

}

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

class A

{

public:

A(int i)

{

}

};

int main()

{

A a;

return 0;

}

這時,編譯器就不會自動生成默認的無參構(gòu)造函數(shù)了,這段代碼會編譯出錯,提示 A 沒有合適的無參構(gòu)造函數(shù):

error C2512: ‘A’ : no appropriate default constructor available

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

class A

{

public:

A() = default;

A(int i)

{

}

};

int main()

{

A a;

return 0;

}

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

//a.h

class A

{

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ù)的實現(xiàn)。有了=default 關(guān)鍵字,我們就可以在 a.h 中直接寫成:

//a.h

class A

{

public:

A() = default;

~A() = default;

};

//a.cpp

#include “a.h”

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

3.4 =delete 語法

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

class A

{

public:

A() = default;

~A() = default;

private:

A(const A& a)

{

}

A& operator =(const A& a)

{

}

};

int main()

{

A a1;

A a2(a1);

A a3;

a3 = a1;

return 0;

}

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

error C2248: ‘A::A’ : cannot access private member declared in class ‘A’

error C2248: ‘A::operator =’ : cannot access private member declared in class ‘A’

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

class A

{

public:

A() = default;

~A() = default;

public:

A(const A& a) = delete;

A& operator =(const A& a) = delete;

};

int main()

{

A a1;

//A a2(a1);

A a3;

//a3 = a1;

return 0;

}

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

//這是一個字符轉(zhuǎn)碼工具類

class EncodeUtil

{

public:

static std::wstring AnsiiToUnicode(const std::string& strAnsii);

static std::string UnicodeToAnsii(const std::wstring& strUnicode);

static std::string AnsiiToUtf8(const std::string& strAnsii);

static std::string Utf8ToAnsii(const std::string& strUtf8);

static std::string UnicodeToUtf8(const std::wstring& strUnicode);

static std::wstring Utf8ToUnicode(const std::string& strUtf8);

private:

EncodeUtil() = delete;

~EncodeUtil() = delete;

EncodeUtil(const EncodeUtil& rhs) = delete;

EncodeUtil& operator=(const EncodeUtil& rhs) = delete;

};

案例 4:對多線程的支持

我們來看一個稍微復(fù)雜一點的例子。

在 C++11 之前,由于 C++98/03 本身缺乏對線程和線程同步原語的支持,我們要寫一個生產(chǎn)者消費者邏輯要這么寫。

在 Windows 上:

/**

* RecvMsgTask.h

*/

class CRecvMsgTask : public CThreadPoolTask

{

public:

CRecvMsgTask(void);

~CRecvMsgTask(void);

public:

virtual int Run();

virtual int Stop();

virtual void TaskFinish();

BOOL AddMsgData(CBuffer* lpMsgData);

private:

BOOL HandleMsg(CBuffer* lpMsg);

private:

HANDLE m_hEvent;

CRITICAL_SECTION m_csItem;

HANDLE m_hSemaphore;

std::vector《CBuffer*》 m_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;

}

}

int CRecvMsgTask::Run()

{

HANDLE hWaitEvent[2];

DWORD dwIndex;

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)

{

//消費者從隊列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);

delete lpMsg;

}

return 0;

}

int CRecvMsgTask::Stop()

{

m_HttpClient.SetCancalEvent();

::SetEvent(m_hEvent);

return 0;

}

void CRecvMsgTask::TaskFinish()

{

}

//生產(chǎn)者調(diào)用這個方法將Task放入隊列m_arrItem中

BOOL CRecvMsgTask::AddMsgData(CBuffer * lpMsgData)

{

if (NULL == lpMsgData)

return FALSE;

::EnterCriticalSection(&m_csItem);

m_arrItem.push_back(lpMsgData);

::LeaveCriticalSection(&m_csItem);

::ReleaseSemaphore(m_hSemaphore, 1, NULL);

return TRUE;

}

Linux 下:

#include 《pthread.h》

#include 《errno.h》

#include 《unistd.h》

#include 《list》

#include 《semaphore.h》

#include 《iostream》

class Task

{

public:

Task(int taskID)

{

this-》taskID = taskID;

}

void doTask()

{

std::cout 《《 “handle a task, taskID: ” 《《 taskID 《《 “, threadID: ” 《《 pthread_self() 《《 std::endl;

}

private:

int taskID;

};

pthread_mutex_t mymutex;

std::list《Task*》 tasks;

pthread_cond_t mycv;

void* consumer_thread(void* param)

{

Task* pTask = NULL;

while (true)

{

pthread_mutex_lock(&mymutex);

while (tasks.empty())

{

//如果獲得了互斥鎖,但是條件不合適的話,pthread_cond_wait會釋放鎖,不往下執(zhí)行。

//當發(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();

delete pTask;

pTask = NULL;

}

return NULL;

}

void* producer_thread(void* param)

{

int taskID = 0;

Task* pTask = NULL;

while (true)

{

pTask = new Task(taskID);

pthread_mutex_lock(&mymutex);

tasks.push_back(pTask);

std::cout 《《 “produce a task, taskID: ” 《《 taskID 《《 “, threadID: ” 《《 pthread_self() 《《 std::endl;

pthread_mutex_unlock(&mymutex);

//釋放信號量,通知消費者線程

pthread_cond_signal(&mycv);

taskID ++;

//休眠1秒

sleep(1);

}

return NULL;

}

int main()

{

pthread_mutex_init(&mymutex, NULL);

pthread_cond_init(&mycv, NULL);

//創(chuàng)建5個消費者線程

pthread_t consumerThreadID[5];

for (int i = 0; i 《 5; ++i)

pthread_create(&consumerThreadID[i], NULL, consumer_thread, NULL);

//創(chuàng)建一個生產(chǎn)者線程

pthread_t producerThreadID;

pthread_create(&producerThreadID, NULL, producer_thread, NULL);

pthread_join(producerThreadID, NULL);

for (int i = 0; i 《 5; ++i)

pthread_join(consumerThreadID[i], NULL);

pthread_cond_destroy(&mycv);

pthread_mutex_destroy(&mymutex);

return 0;

}

怎么樣?上述代碼如果對于新手來說,望而卻步。

為了實現(xiàn)這樣的功能在 Windows 上你需要掌握線程如何創(chuàng)建、線程同步對象 CriticalSection、Event、Semaphore、WaitForSingleObject/WaitForMultipleObjects 等操作系統(tǒng)對象和 API。

在 Linux 上需要掌握線程創(chuàng)建,你需要了解線程創(chuàng)建、互斥體、條件變量。

對于需要支持多個平臺的開發(fā),需要開發(fā)者同時熟悉上述原理并編寫多套適用不同平臺的代碼。

C++11 的線程庫改變了這個現(xiàn)狀,現(xiàn)在你只需要掌握 std::thread、std::mutex、std::condition_variable 少數(shù)幾個線程同步對象即可,同時使用這些對象編寫出來的代碼也可以跨平臺。示例如下:

#include 《thread》

#include 《mutex》

#include 《condition_variable》

#include 《list》

#include 《iostream》

class Task

{

public:

Task(int taskID)

{

this-》taskID = taskID;

}

void doTask()

{

std::cout 《《 “handle a task, taskID: ” 《《 taskID 《《 “, threadID: ” 《《 std::get_id() 《《 std::endl;

}

private:

int taskID;

};

std::mutex mymutex;

std::list《Task*》 tasks;

std::condition_variable mycv;

void* consumer_thread()

{

Task* pTask = NULL;

while (true)

{

std::unique_lock《std::mutex》 guard(mymutex);

while (tasks.empty())

{

//如果獲得了互斥鎖,但是條件不合適的話,pthread_cond_wait會釋放鎖,不往下執(zhí)行。

//當發(fā)生變化后,條件合適,pthread_cond_wait將直接獲得鎖。

mycv.wait(guard);

}

pTask = tasks.front();

tasks.pop_front();

if (pTask == NULL)

continue;

pTask-》doTask();

delete pTask;

pTask = NULL;

}

return NULL;

}

void* producer_thread()

{

int taskID = 0;

Task* pTask = NULL;

while (true)

{

pTask = new Task(taskID);

//使用括號減小guard鎖的作用范圍

{

std::lock_guard《std::mutex》 guard(mymutex);

tasks.push_back(pTask);

std::cout 《《 “produce a task, taskID: ” 《《 taskID 《《 “, threadID: ” 《《 std::get_id() 《《 std::endl;

}

//釋放信號量,通知消費者線程

mycv.notify_one();

taskID ++;

//休眠1秒

std::seconds(1));

}

return NULL;

}

int main()

{

//創(chuàng)建5個消費者線程

std::thread consumer1(consumer_thread);

std::thread consumer2(consumer_thread);

std::thread consumer3(consumer_thread);

std::thread consumer4(consumer_thread);

std::thread consumer5(consumer_thread);

//創(chuàng)建一個生產(chǎn)者線程

std::thread producer(producer_thread);

producer.join();

consumer1.join();

consumer2.join();

consumer3.join();

consumer4.join();

consumer5.join();

return 0;

}

感覺如何?代碼既簡潔又統(tǒng)一。

這就是 C++11 之后使用 Modern C++ 開發(fā)的效率!

C++11 之后的 C++ 更像一門新的語言。

當 C++11 的編譯器發(fā)布之后(Visual Studio 2013、g++4.8),我第一時間更新了我的編譯器,同時把我們的項目使用了 C++11 特性進行了改造。

當然,例子還有很多,限于文章篇幅,這里就列舉 4 個案例。

編輯:jq

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

    關(guān)注

    22

    文章

    2120

    瀏覽量

    76578
  • 編譯器
    +關(guān)注

    關(guān)注

    1

    文章

    1665

    瀏覽量

    50965

原文標題:提升 C++ 開發(fā)效率的幾個小技巧

文章出處:【微信號:gh_3980db2283cd,微信公眾號:開關(guān)電源芯片】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

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

掃碼添加小助手

加入工程師交流群

    評論

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

    技能+1!如何在樹莓派上使用C++控制GPIO?

    在使用樹莓派時,會發(fā)現(xiàn)Python和Scratch是許多任務(wù)(包括GPIO編程)中最常用的編程語言。但知道嗎,也可以使用C++進行GP
    的頭像 發(fā)表于 08-06 15:33 ?3212次閱讀
    技能+1!如何在樹莓派上使用<b class='flag-5'>C++</b>控制GPIO?

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

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

    編譯錯誤: error: unrecognizable insn,不知道原因,請教!

    用start_gui.exe生成的代碼,再用SEGGER Embedded打開,編譯有錯,不知道是什么原因,請教各位大佬?
    發(fā)表于 06-23 14:45

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

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

    不知道怎么畫原理圖了

    時,這樣的問題,也有這么多?!1、電阻的表示方法是第一種,還是第二種?中間是方框還是折線?方框做多大?現(xiàn)場一片混亂立馬分成N派。普通的電阻都這樣,這么多種電阻現(xiàn)
    的頭像 發(fā)表于 04-30 18:40 ?709次閱讀
    <b class='flag-5'>不知道</b>怎么畫原理圖了

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

    隨著搭載HarmonyOS 5的Pura X發(fā)布,鴻蒙生態(tài)進入快車道,各應(yīng)用正在加速適配開發(fā),越來越多開發(fā)者加入到鴻蒙應(yīng)用開發(fā)浪潮中。為提升鴻蒙應(yīng)用
    發(fā)表于 04-18 14:43

    關(guān)于FLASHXIP下載問題求解

    1、環(huán)境是: Nuclei Studio IDE for C/C++ Developers Version: 2023-10 2、開發(fā)板是正點原子達芬奇 這是跑不起來程序,不知道
    發(fā)表于 04-17 07:21

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

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

    C++學到什么程度可以找工作?

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

    源代碼加密、源代碼防泄漏c/c++與git服務(wù)器開發(fā)環(huán)境

    源代碼加密對于很多研發(fā)性單位來說是至關(guān)重要的,當然每家企業(yè)的業(yè)務(wù)需求不同所用的開發(fā)環(huán)境及開發(fā)語言也不盡相同,今天主要來講一下c++及git開發(fā)環(huán)境的源代碼防泄密保護方案。企業(yè)源代碼泄密
    的頭像 發(fā)表于 02-12 15:26 ?750次閱讀
    源代碼加密、源代碼防泄漏<b class='flag-5'>c</b>/<b class='flag-5'>c++</b>與git服務(wù)器<b class='flag-5'>開發(fā)</b>環(huán)境

    測的值不定然后開始減小直到為0,不知道怎么回事?

    ADS1247對寄存器可讀可寫 可是配置完02這個地址的時(寫0x30)在vrefout測不到2.048v,測的值不定然后開始減小直到為0,不知道怎么回事?
    發(fā)表于 01-21 06:27

    Spire.XLS for C++組件說明

    開發(fā)人員可以快速地在 C++ 平臺上完成對 Excel 的各種編程操作,如根據(jù)模板創(chuàng)建新的 Excel 文檔,編輯現(xiàn)有 Excel 文檔,以及對 Excel 文檔進行轉(zhuǎn)換。 Spire.XLS
    的頭像 發(fā)表于 01-14 09:40 ?1211次閱讀
    Spire.XLS for <b class='flag-5'>C++</b>組件說明

    AKI跨語言調(diào)用庫神助攻C/C++代碼遷移至HarmonyOS NEXT

    產(chǎn)品創(chuàng)新與功能迭代,而非技術(shù)遷移的細節(jié)問題,大幅提升開發(fā)效率。 據(jù)悉,在涉及C/C++/ETS跨越語言調(diào)用的鴻蒙化應(yīng)用中,有超過80%的項目
    發(fā)表于 01-02 17:08

    有關(guān)UV固化不知道的技術(shù)細節(jié)

    UV固化技術(shù)中,光引發(fā)劑吸收UV光產(chǎn)生活性自由基觸發(fā)聚合反應(yīng),包括鏈引發(fā)、增長、終止和交聯(lián)。反應(yīng)速率受UV光強、光引發(fā)劑濃度、單體類型等因素影響,UV固化技術(shù)具有快速固化特性。
    的頭像 發(fā)表于 12-06 09:33 ?1305次閱讀

    C7000優(yōu)化C/C++編譯器

    電子發(fā)燒友網(wǎng)站提供《C7000優(yōu)化C/C++編譯器.pdf》資料免費下載
    發(fā)表于 10-30 09:45 ?0次下載
    <b class='flag-5'>C</b>7000優(yōu)化<b class='flag-5'>C</b>/<b class='flag-5'>C++</b>編譯器