面試常見問題,c++11新特性

新特性

  1. auto關鍵字,編譯器根據上下文情況確定auto的真正類型
  2. decltype ,有點類似於auto的反函數,能夠獲取變量類型 int a=1; decltype(a) b=a;
  3. nullptr ,空指針,爲了解決原來C++中NULL的二義性問題而引進的一種新的類型,因爲NULL實際上代表的是0
void F(int a){
	cout<<a<<endl;
}
void F(int *p){
	assert(p!=NULL);
	cout<<*p<<endl;
}
int main(){
	int *p=nullptr;
	int *q=NULL;
	bool equal=(p==q);// equal的值爲true,說明p和q都是空指針  
	int a=nullptr;// 編譯失敗,nullptr不能轉型爲int  
	F(0);// 在C++98中編譯失敗,有二義性;在C++11中調用F(int)  
	F(nullptr);
}
  1. 序列for循環,可以用來遍歷數組和容器、string。
map<string,int> m{{"a",1},{"b",2},{"c",3}};
for (auto p :m){
	cout<<p.first<<":"<<p.second<<endl;
}
  1. lambda
    c11中引入的新技術,所有lambda的表達式都可以用更復雜的代碼來表示,因此可以說是一種語法糖。
// 定義簡單的lambda表達式 ,就像一種定義函數的快速方式
auto basicLambda = [] { cout << "Hello, world!" << endl; };
// 調用
basicLambda();   // 輸出:Hello, world!

// 指明返回類型
auto add = [](int a, int b) -> int { return a + b; };// 自動推斷返回類型
auto multiply = [](int a, int b) { return a * b; };


int sum = add(2, 5);   // 輸出:7
int product = multiply(2, 5);  // 輸出:10

同時可以捕捉定義區間的內的數值

int main(){
	int x = 10;
	auto add_x = [x](int a) { return a + x; }; // 複製捕捉x
	auto multiply_x = [&x](int a) { return a * x; }; // 引用捕捉x
	cout << add_x(10) << " " << multiply_x(10) << endl;
	// 輸出:20 100
	return 0;
}
	 []:默認不捕獲任何變量;
	[=]:默認以值捕獲所有變量;
	[&]:默認以引用捕獲所有變量;
	[x]:僅以值捕獲x,其它變量不捕獲;
	[&x]:僅以引用捕獲x,其它變量不捕獲;
	[=, &x]:默認以值捕獲所有變量,但是x是例外,通過引用捕獲;
	[&, x]:默認以引用捕獲所有變量,但是x是例外,通過值捕獲;		
	[this]:通過引用捕獲當前對象(其實是複製指針);
	[*this]:通過傳值方式捕獲當前對象;
  1. 容器的初始化方式 實際上用了模板的initializer list
int arr[3]={1,2,3};
vector<int> vec={1,2,3};
map<int,string> m={{1,"a"},{2,"b"}};
string str={"hello world"};

還可以作爲參數輸入

#include<iostream>
#include<vector>
using namespace std;
template <typename &T>
class MyArray{
private:
	vector<T> m_Array;
public:
	MyArray(){}
	MyArray(const initializer_list<T>& il){
		for(auto x:il)
			m_Array.push_bach(x);
	}
};
int main()
{
    MyArray<int> foo = { 3, 4, 6, 9 };
    return 0;
    //就不用先定義一個vector再傳入。
}
  1. 返回值的推導,可以用auto設置函數返回值,編譯器根據上下文推導返回值。

  2. 智能指針
    c++11:
    1.shared_ptr
    2.unique_ptr
    3.weak_ptr
    4.auto_ptr(被棄用)

Class shared_ptr 實現共享式擁有(shared ownership)概念。多個智能指針指向相同對象,該對象和其相關資源會在 “最後一個 reference 被銷燬” 時被釋放。爲了在結構較複雜的情景中執行上述工作,標準庫提供 weak_ptr、bad_weak_ptr 和 enable_shared_from_this 等輔助類
Class unique_ptr 實現獨佔式擁有(exclusive ownership)或嚴格擁有(strict ownership)概念,保證同一時間內只有一個智能指針可以指向該對象。你可以移交擁有權。它對於避免內存泄漏(resource leak)——如 new 後忘記 delete ——特別有用

shared_ptr
多個指針共享同一個對象,最後一個指針負責銷燬對象釋放內存

可以防範Cross-DLL問題(對象在動態鏈接庫(DLL)中被 new 創建,卻在另一個 DLL 內被 delete 銷燬)、自動解除互斥鎖

weak_ptr
weak_ptr 允許你共享但不擁有某對象,一旦最末一個擁有該對象的智能指針失去了所有權,任何 weak_ptr 都會自動成空(empty)。因此,在 default 和 copy 構造函數之外,weak_ptr 只提供 “接受一個 shared_ptr” 的構造函數。

可打破環狀引用(cycles of references,兩個其實已經沒有被使用的對象彼此互指,使之看似還在 “被使用” 的狀態)的問題

#include <iostream>  
#include <string>  
#include <memory>  
using namespace std;  
  
class A;  
class B;  
  
  
class A{  
public:  
    ~A(){ cout << "destroying A\n" ; }  
    shared_ptr<B> pb;  
};  
  
class B{  
public:  
    ~B(){ cout << "destroying B\n" ; }  
    shared_ptr<A> pa;  
};  
  
void test(){  
    shared_ptr<A> a(new A());  
    shared_ptr<B> b(new B());  
  
    a->pb = b;  
    b->pa = a;  
}  
  
int main(){  
    cout << "begin test...\n";  
    test();  
    cout << "end test\n";  
}  
  
output:  
begin test...  
end test  


 class B{  
 public:  
    ~B(){ cout << "destroying B\n" << endl; }  
    weak_ptr<A> pa;  
 }; 

unique_ptr
unique_ptr 是 C++11 纔開始提供的類型,是一種在異常時可以幫助避免資源泄漏的智能指針。採用獨佔式擁有,意味着可以確保一個對象和其相應的資源同一時間只被一個 pointer 擁有。一旦擁有着被銷燬或編程 empty,或開始擁有另一個對象,先前擁有的那個對象就會被銷燬,其任何相應資源亦會被釋放。

取代auto_ptr

dynamic_cast

dynamic_cast 運算符的主要用途:將基類的指針或引用安全地轉換成派生類的指針或引用,並用派生類的指針或引用調用非虛函數。如果是基類指針或引用調用的是虛函數無需轉換就能在運行時調用派生類的虛函數。
這個函數常用於對基類和派生類之間的指針轉化,比如

struct Base {
        virtual ~Base() {}
   };
   struct Derived : Base {
       void df() { std::cout << "df()\n"; }
   };
   Base* bp1 = new Base;
   Base* bp2 = new Derived;
   if (Derived* p = dynamic_cast<Derived*>(bp1)) // 轉型失敗,返回 nullptr
       p->df();  // 不執行
   if (auto p = dynamic_cast<Derived*>(bp2)) // 轉型成功
       p->df();  // 執行

if內部可以初始化

if 語句在c17之後的變化,從上面的代碼中我們可以看到,可以在判斷語句中加入初始化語句

if (int i=3; i > 2) {
        std::cout << i << " > 2\n";
    } else {
        std::cout << i << " <= 2\n";
    }if (int i=3) {
        std::cout << i << " > 2\n";
    } else {
        std::cout << i << " <= 2\n";
    }
都會輸出3>2,即在判斷語句上可以加入賦值語句,如果後面跟判斷則要用;隔開。

for可以用初始化列表來取值

std::vector<int> v={1,2,3,4,6};
    for (auto&i :v)
        i+=1;
    for (auto i:v)
        std::cout<<i<<" ";
    int a[]={1,23,4,5,6};
    for (auto&i :a)
        i+=1;
    for (auto i:a)
        std::cout<<i<<" ";
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章