c ++ 學習總結

2020-06-03----------------------------------------------------------------------------------------------------------------------------------------------------------

左值引用vs右值引用https://blog.csdn.net/xuyuqingfeng953/article/details/51058236

左值引用和直接傳遞了實參有區別麼?

tuple, forward_as_tuplehttps://www.cnblogs.com/LuckCoder/p/8632209.html

2020-04-03------------------------------------------------------------------------------------------------------------------------------------------------------------------

指針作爲類的成員變量,我想要改變指針的內容,指針的指針和指針的引用還是有區別的,

2020-3-23-----------------------------------------------------------------------------------------------------------------------------------------------------------如果new了一片內存賦值給指針p,通過delete的方式回收了內存,這時內存回收了,但是指針p依然指向這片未分配的內存區域,成爲野指針,結果是不確定的,因而在delete釋放內存的同時,需要手動通過p=nullptr將p置空 。同樣,定義的時候也需要初始化。

C/C++野指針

空指針與野指針

野指針(概念,產生原因,危害,避免方法)

2020-3-20-----------------------------------------------------------------------------------------------------------------------------------------------------------

class A{
A(input){
    temp = input;
}
private:
int temp;
}
A a(5);

std::shared_ptr<A> p(new A);
std::shared_ptr<A> p = std::make_shared<A>(a);
std::shared_ptr<A> p = std::make_shared<A>(5);

make_shared後面跟A類的一個對象或者構造函數裏的參數,都是可以的。 

2020-3-17-----------------------------------------------------------------------------------------------------------------------------------------------------------vector可以assign(n, digit);可以resize(大小),改變size,過大capacity會自動擴容; 也可以 reserve主動擴容,改變capacity.

resize更大之後,好像默認賦值0;resize更小之後,size變小了,但是原來的位置可以訪問,而且還是原來的值,物理內存上的內容並沒有改變.

thread及時回收,防止資源泄露https://www.cnblogs.com/liangjf/p/9801496.html

多線程cmake設置:

find_package (Threads)
add_executable (myapp main.cpp ...)
target_link_libraries (myapp ${CMAKE_THREAD_LIBS_INIT})

互斥鎖std::mutex和條件變量std::condition_variable

——> > > std::mutex: std::mutex是C++中最基本的互斥量,提供了獨佔所有權的特性,std::mutex提供了以下成員函數:

構造函數:std::mutex不允許拷貝構造,也不允許move拷貝,最初產生的mutex對象是處於unlocked狀態的。
lock():調用線程將鎖住該互斥量,線程調用該函數會發生以下3種情況: 
(1)如果該互斥量當前沒有被鎖住,則調用線程將該互斥量鎖住,直到調用unlock之前,該線程一直擁有該鎖。 
(2)如果當前互斥量被其他線程鎖住,則當前的調用線程被阻塞住。 
(3)如果當前互斥量被當前調用線程鎖住,則會產生死鎖,,也就是說同一個線程中不允許鎖兩次。

unlock():解鎖,釋放對互斥量的所有權。

try_lock():嘗試鎖住互斥量,如果互斥量被其他線程佔有,則當前線程也不會被阻塞,線程調用該函數會出現下面3種情況: 
(1)如果當前互斥量沒有被其他線程佔有,則該線程鎖住互斥量,直到該線程調用unlock釋放互斥量。 
(2)如果當前互斥量被其他線程鎖住,則當前調用線程返回false,而並不會被阻塞掉。 
(3)如果當前互斥量被當前調用線程鎖住,則會產生死鎖。

條件變量std::condition_variable:

  條件變量是併發程序設計中的一種控制結構。多個線程訪問一個共享資源(或稱臨界區)時,不但需要用互斥鎖實現獨享訪問以避免併發錯誤(稱爲競爭危害),在獲得互斥鎖進入臨界區後還需要檢驗特定條件是否成立:C++11中引入了條件變量,其相關內容均在<condition_variable>中。這裏主要介紹std::condition_variable類。

(1)、如果不滿足該條件,擁有互斥鎖的線程應該釋放該互斥鎖,把自身阻塞(block)並掛到(suspend)條件變量的線程隊列中

(2)、如果滿足該條件,擁有互斥鎖的線程在臨界區內訪問共享資源,在退出臨界區時通知(notify)在條件變量的線程隊列中處於阻塞狀態的線程,被通知的線程必須重新申請對該互斥鎖加鎖。

  條件變量std::condition_variable用於多線程之間的通信,它可以阻塞一個或同時阻塞多個線程。std::condition_variable需要與std::unique_lock配合使用。std::condition_variable效果上相當於包裝了pthread庫中的pthread_cond_*()系列的函數。

當std::condition_variable對象的某個wait函數被調用的時候,它使用std::unique_lock(通過std::mutex)來鎖住當前線程。當前線程會一直被阻塞,直到另外一個線程在相同的std::condition_variable對象上調用了notification函數來喚醒當前線程。

std::condition_variable對象通常使用std::unique_lock<std::mutex>來等待,如果需要使用另外的lockable類型,可以使用std::condition_variable_any類。

std::condition_variable類的成員函數:

(1)、構造函數:僅支持默認構造函數,拷貝、賦值和移動(move)均是被禁用的。

(2)、wait:當前線程調用wait()後將被阻塞,直到另外某個線程調用notify_*喚醒當前線程;當線程被阻塞時,該函數會自動調用std::mutex的unlock()釋放鎖,使得其它被阻塞在鎖競爭上的線程得以繼續執行。一旦當前線程獲得通知(notify,通常是另外某個線程調用notify_*喚醒了當前線程),wait()函數也是自動調用std::mutex的lock()。

  wait分爲無條件被阻塞和帶條件的被阻塞兩種。

——> > > 無條件被阻塞:調用該函數前,當前線程應該已經對unique_lock<mutex> lck完成了加鎖。所有使用同一個條件變量的線程必須在wait函數中使用同一個unique_lock<mutex>。該wait函數內部會自動調用lck.unlock()對互斥鎖解鎖,使得其他被阻塞在互斥鎖上的線程恢復執行。使用本函數被阻塞的當前線程在獲得通知(notified,通過別的線程調用 notify_*系列的函數)而被喚醒後,wait()函數恢復執行並自動調用lck.lock()對互斥鎖加鎖。

——> > > 帶條件的被阻塞:wait函數設置了謂詞(Predicate),只有當pred條件爲false時調用該wait函數纔會阻塞當前線程,並且在收到其它線程的通知後只有當pred爲true時纔會被解除阻塞。因此,等效於while (!pred())  wait(lck).

(3)、wait_for:與wait()類似,只是wait_for可以指定一個時間段,在當前線程收到通知或者指定的時間超時之前,該線程都會處於阻塞狀態。而一旦超時或者收到了其它線程的通知,wait_for返回,剩下的步驟和wait類似。

(4)、wait_until:與wait_for類似,只是wait_until可以指定一個時間點,在當前線程收到通知或者指定的時間點超時之前,該線程都會處於阻塞狀態。而一旦超時或者收到了其它線程的通知,wait_until返回,剩下的處理步驟和wait類似。

(5)、notify_all: 喚醒所有的wait線程,如果當前沒有等待線程,則該函數什麼也不做。

(6)、notify_one:喚醒某個wait線程,如果當前沒有等待線程,則該函數什麼也不做;如果同時存在多個等待線程,則喚醒某個線程是不確定的(unspecified)。

  條件變化存在虛假喚醒的情況,因此在線程被喚醒後需要檢查條件是否滿足。無論是notify_one或notify_all都是類似於發出脈衝信號,如果對wait的調用發生在notify之後是不會被喚醒的,所以接收者在使用wait等待之前也需要檢查條件是否滿足。

std::condition_variable_any類與std::condition_variable用法一樣,區別僅在於std::condition_variable_any的wait函數可以接受任何lockable參數,而std::condition_variable只能接受std::unique_lock<std::mutex>類型的參數。

std::notify_all_at_thread_exit函數:當調用該函數的線程退出時,所有在cond條件變量上等待的線程都會收到通知。

參考:

https://www.cnblogs.com/depend-wind/articles/10108048.html

https://www.cnblogs.com/zhanghu52030/p/9166737.html

2020-3-11------------------------------------------------------------------------------------------------------------------------------------------------------------

基類A,包含a, b兩個方法,其中a調用了b,且b是virtual;

派生類B,重寫了b,還新寫了個c函數;

基類指針p指向B的對象,不能調用c,因爲他也不知道派生類會有這麼個函數;

p調用函數a的時候,a又調用了函數b,因爲是virtual的且B中也重寫了,因此會調用B中的b。

2020-3-6---------------------------------------------------------------------------------------------------------------------------------------------------------------------

            std::atan(y/x)
            std::atan2(y, x)

atan的情況下,要保證x不會等於0;atan2允許x等於0,不需要特別考慮。做除法就要考慮分佈會不會存在等於0的風險。

不要用abs(), fabs()這種c的庫,統一用std::abs()

 

2020-3-5--------------------------------------------------------------------------------------------------------------------------------------------------------------------

enum 與enum class:

1.3 問題3:enum的作用域
enum的中的 ” { } ” 大括號並沒有將枚舉成員的可見域限制在大括號內,導致enum成員曝露到了上一級作用域(塊語句)中。

例如:

#include <iostream>
enum color{red,blue};//定義擁有兩個成員的enum,red和blue在enum的大括號外部可以直接訪問,而不需要使用域運算符。
int main() {
    std::cout << blue << std::endl;
    std::cin.get();
    return 0;
}

就如上面的代碼,我們可以在blue的大括號之外訪問它,color的成員被泄露到了該文件的全局作用域中(雖然它尚不具備外部鏈接性)。可以直接訪問,而不需要域運算符的幫助。

但是這不是關鍵,有時我們反而覺得非常方便。下面纔是問題所在:

問題:無法定義同名的枚舉成員

enum color { red, blue };
//enum MyEnum { red, yellow }; ERROR, 重定義;以前的定義是“枚舉數”

如上面的代碼所示:我們無法重複使用red這個標識符。因爲它在color中已經被用過了。但是,它們明明就是不同的枚舉類型,如果可以使用相同的成員名稱,然後通過域運算符來訪問的話,該有多好!就像下面這樣:

color::red

但是這是舊版的enum無法做到的。
引入了域,要通過域運算符訪問,不可以直接通過枚舉體成員名來訪問(所以我們可以定義相同的枚舉體成員而不會發生重定義的錯誤)

#include <iostream>

enum class color { red, green, yellow};
enum class colorX { red, green, yellow };

int main() {
    //使用域運算符訪問枚舉體成員,強轉後打印
    std::cout << static_cast<int>(color::red) << std::endl;
    std::cout << static_cast<int>(colorX::red) << std::endl;
    std::cin.get();
    return 0;
}

參考:https://blog.csdn.net/sanoseiichirou/article/details/50180533?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task

 

儘量用using而不是typedef

    //typedef std::shared_ptr<FeatureInfo> FeatureInfo_Ptr;
    using FeatureInfo_Ptr = std::shared_ptr<FeatureInfo>;

push_back(), 已知大小的情況下先reserve(),不需要隨機訪問的情況系下用list

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 

memset

memset()函數原型是extern void *memset(void *buffer, int c, int count)        buffer:爲指針或是數組,

              c:是賦給buffer的值,

       count:是buffer的長度.

int abs(int i);                   // 處理int類型的取絕對值

double fabs(double i); //處理double類型的取絕對值

float fabsf(float i);           /處理float類型的取絕對值

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------

1、vector<Eigen::Matrix4d,Eigen::aligned_allocator<Eigen::Matrix4d>>

2、bitset

3、int*, static_cast<int*>, reinterpret_cast<int*>不一樣;

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------

定義爲虛函數,繼承之後存在同名函數,但是行爲不同,可以使用基類指針或者引用指向;

BCD都繼承自A,可以使用A指針指向,從而做到用數組“保存”不同類型的BCD,不管是什麼類型,如果他們都存在與A的同名虛函數,那麼調用的就是BCD各自的方法,如果沒有定義爲虛函數,那麼在任何情況下調用的都是基類的方法;

 

如果不需要使用基類指針指向不同class,並調用同名函數,也沒必須定義虛函數,反正也不影響調用父類的函數功能

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------chrono計時:

std::chrono::steady_clock::time_point start = std::chrono::steady_clock::now();

        LandmarkFeatureExtracter::extract(scan, features);
        GeometryFeatureExtracter::extract(scan, features);

        std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now();
        std::chrono::steady_clock::duration used_time = end-start;
        std::cout << "used time: " << std::chrono::duration_cast<std::chrono::milliseconds>(used_time).count() << std::endl;

https://www.cnblogs.com/bianchengnan/p/9478638.html

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章