學習地址: http://c.biancheng.net/view/3730.html
8. C++11列表初始化(統(tǒng)一了初始化方式)
- 我們知道,在 C++98/03 中的對象初始化方法有很多種,請看下面的代碼:
//初始化列表
int i_arr[3] = { 1, 2, 3 }; //普通數(shù)組
struct A1
{
int x;
struct B
{
int i;
int j;
} b;
} a = { 1, { 2, 3 } }; //POD類型: POD 類型即 plain old data 類型,簡單來說,是可以直接使用 memcpy 復制的對象。
//拷貝初始化(copy-initialization)
int i = 0;
class Foo1
{
public:
Foo1(int) {}
} foo = 123; //注意這里需要拷貝構造函數(shù)
//直接初始化(direct-initialization)
int j(0);
Foo1 bar(123);
2 .為了統(tǒng)一初始化方式,并且讓初始化行為具有確定的效果,C++11 中提出了列表初始化(List-initialization)的概念。
3 . 在上面我們已經看到了,對于普通數(shù)組和 POD 類型,C++98/03 可以使用初始化列表(initializer list)進行初始化,但是這種初始化方式的適用性非常狹窄,只有上面提到的這兩種數(shù)據(jù)類型可以使用初始化列表。
4 . 在 C++11 中,初始化列表的適用性被大大增加了。它現(xiàn)在可以用于任何類型對象的初始化,請看下面的代碼。
class Foo2
{
public:
Foo2(int) {}
private:
Foo2(const Foo2 &);
Foo2 operator=(const Foo2 &);
};
void testInitializer (){
Foo2 a1(123);
Foo2 a2 = 123; //網站上面說 會報錯error: 'Foo::Foo(const Foo &)' is private。但是我用xcode沒有報錯,斷點進入到了Foo2(int) {}
Foo2 a3 = {123};
Foo2 a4{123};
}
5 . a3、a4 使用了新的初始化方式來初始化對象,效果如同 a1 的直接初始化, 這里需要注意的是,a3 雖然使用了等于號,但它仍然是列表初始化,因此,私有的拷貝構造并不會影響到它。
6 . 注意我把第一個構造函數(shù)改為 explicit Foo2(int) {}之后 a2, a3報錯
7 . 如果真的要用初始化列表,那么最好用a4這種
8 . 另外,如同讀者所想的那樣,new 操作符等可以用圓括號進行初始化的地方,也可以使用初始化列表:
int* a1 = new int { 123 };
double b1 = double { 12.12 };
int* arr1 = new int[3] { 1, 2, 3 };
9 . 除了上面所述的內容之外,列表初始化還可以直接使用在函數(shù)的返回值上:
struct Foo3 {
Foo3(int i, double j){}
};
Foo3 func3() {
return {1, 3};
9. lambda匿名函數(shù)的定義
- 定義一個 lambda 匿名函數(shù)很簡單,可以套用如下的語法格式:
[外部變量訪問方式說明符] (參數(shù)) mutable noexcept/throw() -> 返回值類型 {
函數(shù)體; };
1) [外部變量方位方式說明符]
[ ] 方括號用于向編譯器表明當前是一個 lambda 表達式,其不能被省略。在方括號內部,可以注明當前 lambda 函數(shù)的函數(shù)體中可以使用哪些“外部變量”。
所謂外部變量,指的是和當前 lambda 表達式位于同一作用域內的所有局部變量。
2) (參數(shù))
和普通函數(shù)的定義一樣,lambda 匿名函數(shù)也可以接收外部傳遞的多個參數(shù)。和普通函數(shù)不同的是,如果不需要傳遞參數(shù),可以連同 () 小括號一起省略;
3) mutable
此關鍵字可以省略,如果使用則之前的 () 小括號將不能省略(參數(shù)個數(shù)可以為 0)。默認情況下,對于以值傳遞方式引入的外部變量,不允許在 lambda 表達式內部修改它們的值(可以理解為這部分變量都是 const 常量)。而如果想修改它們,就必須使用 mutable 關鍵字。
注意,對于以值傳遞方式引入的外部變量,lambda 表達式修改的是拷貝的那一份,并不會修改真正的外部變量;
4) noexcept/throw()
可以省略,如果使用,在之前的 () 小括號將不能省略(參數(shù)個數(shù)可以為 0)。默認情況下,lambda 函數(shù)的函數(shù)體中可以拋出任何類型的異常。而標注 noexcept 關鍵字,則表示函數(shù)體內不會拋出任何異常;使用 throw() 可以指定 lambda 函數(shù)內部可以拋出的異常類型。
值得一提的是,如果 lambda 函數(shù)標有 noexcept 而函數(shù)體內拋出了異常,又或者使用 throw() 限定了異常類型而函數(shù)體內拋出了非指定類型的異常,這些異常無法使用 try-catch 捕獲,會導致程序執(zhí)行失?。ū竟?jié)后續(xù)會給出實例)。
5) -> 返回值類型
指明 lambda 匿名函數(shù)的返回值類型。值得一提的是,如果 lambda 函數(shù)體內只有一個 return 語句,或者該函數(shù)返回 void,則編譯器可以自行推斷出返回值類型,此情況下可以直接省略-> 返回值類型。
6) 函數(shù)體
和普通函數(shù)一樣,lambda 匿名函數(shù)包含的內部代碼都放置在函數(shù)體中。該函數(shù)體內除了可以使用指定傳遞進來的參數(shù)之外,還可以使用指定的外部變量以及全局范圍內的所有全局變量。
2 . ??需要注意的是,外部變量會受到以值傳遞還是以引用傳遞方式引入的影響,而全局變量則不會。換句話說,在 lambda 表達式內可以使用任意一個全局變量,必要時還可以直接修改它們的值。
3 . 比如,如下就定義了一個最簡單的 lambda 匿名函數(shù):[]{}
4 . 外部變量格式 功能
[] 空方括號表示當前 lambda 匿名函數(shù)中不導入任何外部變量。
[=] 只有一個 = 等號,表示以值傳遞的方式導入所有外部變量;
[&] 只有一個 & 符號,表示以引用傳遞的方式導入所有外部變量;
[val1,val2,…] 表示以值傳遞的方式導入 val1、val2 等指定的外部變量,同時多個變量之間沒有先后次序;
[&val1,&val2,…] 表示以引用傳遞的方式導入 val1、val2等指定的外部變量,多個變量之間沒有前后次序;
[val,&val2,…] 以上 2 種方式還可以混合使用,變量之間沒有前后次序。
[=,&val1,…] 表示除 val1 以引用傳遞的方式導入外,其它外部變量都以值傳遞的方式導入。
[this] 表示以值傳遞的方式導入當前的 this 指針。文章來源:http://www.zghlxwxcb.cn/news/detail-639270.html
5 . ??注意,單個外部變量不允許以相同的傳遞方式導入多次。例如 [=,val1] 中,val1 先后被以值傳遞的方式導入了 2 次,這是非法的。文章來源地址http://www.zghlxwxcb.cn/news/detail-639270.html
void testLambda() {
int num[4]{2,5,3,4};
sort(num, num+4, [num](int x, int y)->bool{return x < y;});
cout<< "sort:" <<endl;
for (auto &n: num) {
cout<< n <<endl;
}
}
到了這里,關于面試之快速學習c++11- 列表初始化和 lambda匿名函數(shù)的定義的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!