262-C++ C11标准
1.C++中的類型轉換分為四種形式:
C語言中的轉換都是沒有意義的,就是說C語言中的強轉都是(int) (int*)這樣的類型,你不知道它這么轉的意義是什么,意義不夠明確,所以C++中給出了4種類型轉換
①static_cast:值的轉換,相當于C語言中的強轉,這個轉換意義很明確就是將float類型轉成整型
int a = 10; float ft = 12.23; a = static_cast<int>(ft);//轉成int ft = static_cast<float>(a);//轉成float②const_cast:是去常性強轉,C語言的這種方式int* p = (int*)&a;的意義并不明確,而C++中的int* p = const_cast<int*>(&a);意義非常明確,就是去常性
const int a = 10; int* p = (int*)&a;//C語言方式 int* p = const_cast<int*>(&a);//C++方式③reinterpret_cast:是對指針進行重新解釋的轉換
int a = 10; int* p = &a; char* cp = (char*)&a;//C語言方式 char* cp = reinterpret_cast<char*>(&a);④dynamic_cast:動態強制類型轉換:將子對象的地址強轉成父指針
Object* op = NULL; Base* bp = NULL;Object obj; Base base;op = &base;//C方式ok bp = &Object;//C方式,error op = dynamic_cast<Object*>(&base);//C++,ok bp = dynamic_cast<Object*>(&base);//error就是說C++使類型轉換的意義更明確了
2.std::move移動構造函數的內部是怎樣實現
my_remove_reference可以移除引用特質,也就是說無論傳進來的是int類型,還是int&類型,還是int&&類型,type永遠都是int類型
template<class _Ty> struct my_remove_reference {using type = _Ty;using Const_thru_ref_type = const _Ty; };template<class _Ty> struct my_remove_reference<_Ty&> {using type = _Ty;using Const_thru_ref_type = const _Ty&; };template<class _Ty> struct my_remove_reference<_Ty&&> {using type = _Ty;using Const_thru_ref_type = const _Ty&&; };template<class _Ty> using my_remove_reference_t = typename my_remove_reference<_Ty>::type;template<class _Ty> my_remove_reference_t<_Ty>&& my_move(_Ty&& _Arg) {return static_cast<my_remove_reference_t<_Ty>&&>(_Arg); }int main(){my_remove_reference<int>::type;//type是int類型my_remove_reference<int&>::type;//type是int類型my_remove_reference<int&&>::type;//type是int類型return 0; }也就是說std::move不管傳進來的是int類型,還是int&類型,還是int&&類型,都會通過重命名using type = _Ty;使type一直保持是int類型,然后通過static_cast轉成右值去調用移動構造函數
template<class _Ty> struct my_remove_reference {my_remove_reference() { cout << "_Ty" << endl; }using type = _Ty;using Const_thru_ref_type = const _Ty; };template<class _Ty> struct my_remove_reference<_Ty&> {my_remove_reference() { cout << "_Ty&" << endl; }using type = _Ty;using Const_thru_ref_type = const _Ty&; };template<class _Ty> struct my_remove_reference<_Ty&&> {my_remove_reference() { cout << "_Ty&&" << endl; }using type = _Ty;using Const_thru_ref_type = const _Ty&&; };template<class _Ty> using my_remove_reference_t = typename my_remove_reference<_Ty>::type;template<class _Ty> my_remove_reference_t<_Ty>&& my_move(_Ty&& _Arg) {return static_cast<my_remove_reference_t<_Ty>&&>(_Arg); }int main(){string s0("sun");string s1("hello");//左值string s2("nihao");//左值const string& s3 = s0;//常性左值引用string& s4 = s1;//左值引用string&& s5 = string("nihaohello");//s4左值string s6(my_move(s2));string s7(my_move(s3));//s7和s3都是sun,因為是const,會調用拷貝構造函數string s8(my_move(s4));//s4空,s8hellostring s9(my_move(s5));//s5空,s8nihaohelloreturn 0; }注意:它并不能去掉常性,所以這種方式是很安全的,對于s3來說,他是個常引用,把它的資源交給s7是不允許的,所以會調用拷貝構造函數,給s7賦值,所以s3和s7的值是一樣的,同樣對于移動賦值來說也是一樣的
只有int &&r = 10;這種是右值引用,const int&& x = 100;是一個左值常性引用
對于下面模板來說,_Ty&& a屬于型別未定義(就是說還不確定a是一個什么類型),他可以接收左值、右值、引用都可以
template<class _Ty> void fun(_Ty&& a) {}3.會實例化出兩個版本,一個是Base<0>,一個是Base<1>
4.在模板類中,引用的疊加問題,所有情況下a都是一個左值
在C11標準之前,函數的重載依靠的是形參列表的不同來進行重載的,在C11標準以后,引入了左值、右值、將亡值的概念,如果這個變量可以取地址,就是一個左值,如果這個變量不能取地址,就是一個右值,如果這個變量是在表達式中或者在函數的返回中,就是一個將亡值,一般將亡值可以處理成右值,但是將亡值一旦具有名了,就是一個左值了
所以C++可以根據是否是左值還是右值進行重載
void fun(int&); void fun(const int&); void fun(int&&);可以看到所有情況下a都是左值,Add函數的返回值作為參數傳遞進去以后,也被當成了左值來處理
當使用完美轉發時,20是一個右值,傳給a后,依然保持著右值的屬性,Add函數返回值是一個將亡值,完美轉發情況下,保持其右值的屬性不變
所以完美轉發的作用就是使在程序的運行過程中,使變量的屬性不變
左值和右值疊加是左值
左值和左值疊加是左值
右值和左值疊加是左值
右值和右值疊加是右值
5.auto的初始化類型的方式
auto是一個占位符,當auto在推導的時候,auto x = 10;在編譯的時候就會推導出auto是一個int類型,然后用int類型替換掉auto
const int e = 10; auto f = e;推導出f的類型是int類型,auto& f1 = e;推導出f1是一個const int類型,因為f1是e的引用,不能而e是一個const類型,所以f1也必須是const類型
只有是靜態常性整型量static const auto num = 0;時,可以直接初始化,其他情況不能直接初始化
注意:auto不能作為函數的參數
6.C11標準中,在定義類型的時候,可以預給值,并不是真的給值,當調用默認構造函數的時候,會用預值進行初始化
是在構建對象時,調用默認構造函數的時候,用預值進行的初始化
當實現了構造函數時,就不能調用默認構造函數了
如果構造函數有默認值,就必須都傳遞參數
如果構造函數沒有參數默認值,這樣就都可以編譯通過
auto不能用于推導 集合當中
auto可以推演出函數的返回類型,這兩種方式都是可以的,但是前提是你自己心里要清楚begin的返回值是一個什么樣的迭代器類型,這樣使用auto就可以簡寫,很方便
auto并沒有性能的提升,只是編寫代碼更方便了,但是對于瀏覽源碼來說也帶來了一定的難度,對于開發者來說,別人不容易讀懂我的代碼了,可以帶來效益
7.decltype是一個操作符,可以根據表達式推演出類型
decltype也可以推導出函數的返回值類型,一般情況下都用不到decltype
8.nullptr和NULL的區別
系統在定義NULL的時候,如果是C++,就把NULL定義成了0,否則就把0強轉成無類型((void*)0)
對于編譯器來說,無論是0還是無類型0都具有二義性,都把他當作一個整型來看待,C11為了解決這個問題,引入了一個關鍵字nullptr,它是一個關鍵字,認為它是一個空指針常量,nullptr可以給一切指針類型賦值,所以在編寫程序時,盡可能的使用nullptr
9.C11標準中初始化方式
10.Object a();編譯器會認為這是一個聲明,Object();是類型加括號,會調用構造函數
總結
以上是生活随笔為你收集整理的262-C++ C11标准的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: asp.net 开发注意的几点
- 下一篇: 【面试】c++单例模式