C++知識點整理(一)
C++11 ,14,17 出來好多年了,但是一直沒有系統的去整理一凡。
趁著這段時間比較空,來一波溫故而知新。
有一些新概念,還有一些竟然自己一直理解錯了或者被人誤導了。
有些東西我覺得是多餘的東西,但是可以用來幫助看
開原始碼
吧
1。C++型別後置(C++11的玩法,在14以後的版本里已經沒必要了)
這種其實就是一種語法糖吧,想不出實際用途在哪。
難道是想用auto來自動推導模板的返回值。
template
auto add(T t, U u) -> decltype(t + u)
{
return t + u;
}
2。完美轉發 std::forward
首先解釋一下什麼是完美轉發,它指的是函式模板可以將自己的引數“完美”地轉發給內部呼叫的其它函式。所謂完美,即不僅能準確地轉發引數的值,還能保證被轉發引數的左、右值屬性不變。
完美轉發這樣嚴苛的引數傳遞機制,很常用嗎?C++98/03 標準中幾乎不會用到,但 C++11 標準為 C++ 引入了右值引用和移動語義,因此很多場景中是否實現完美轉發,直接決定了該引數的傳遞過程使用的是複製語義(呼叫複製建構函式)還是移動語義(呼叫移動建構函式)。
因為引入了移動複製函式,左值,又值等概念,所以這個還是挺常用的,特別是在stl原始碼裡有很多。
#include
using namespace std;
//過載被呼叫函式,檢視完美轉發的效果
void otherdef(int & t) {
cout << “lvalue\n”;
}
void otherdef(const int & t) {
cout << “rvalue\n”;
}
//實現完美轉發的函式模板
template
void function(T&& t) {
otherdef(forward
}
int main()
{
function(5);
int x = 1;
function(x);
return 0;
}
輸出為
rvalue
lvalue
3。返回值最佳化
返回值最佳化
(Return value optimization,縮寫為RVO)是C++的一項編譯最佳化技術,即刪除保持函式返回值的臨時物件。這可能會省略兩次複製建構函式,即使複製建構函式有副作用。典型地,當一個函式返回一個物件例項,一個臨時物件將被建立並透過
複製建構函式
把目標物件複製給這個臨時物件。C++標準允許省略這些複製建構函式,即使這導致程式的不同行為,即使編譯器把兩個物件視作同一個具有副作用。
備註,我以前的認知裡,函式返回值的的時候,會複製一份。例如如下程式碼
應該會呼叫2次建構函式,一次複製建構函式,而實際上則是執行了一次建構函式 + 一次移動建構函式。
class A
{
public:
A();
~A();
A(const A& d);
A(A&& d);//移動建構函式
};
A::A()
{
printf(“construction !!\n”);
}
A::A(A&& d)
{
printf(“construction move !!\n”);
}
A::A(const A& d)
{
printf(“construction copy !!\n”);
}
A::~A()
{
}
A func()
{
A a;
return a;
}
int main() {
A b = func();
}
輸出
construction !!
construction move !!
4。函式模板的預設模板引數
函式模板有預設引數這事倒真沒使用過,做個記錄吧,一些開原始碼裡很常見。
如果能夠從函式實參中推匯出型別的話,那麼預設模板引數就不會被使用,反之,預設模板引數則可能會被使用
比如STL原始碼裡的這部分程式碼
template
struct integral_constant {
static constexpr _Ty value = _Val;
using value_type = _Ty;
using type = integral_constant;
constexpr operator value_type() const noexcept {
return value;
}
_NODISCARD constexpr value_type operator()() const noexcept {
return value;
}
};
template
using
bool_constant
= integral_constant
using true_type = bool_constant
using false_type = bool_constant
5。列表初始化
(1)。 型別是一個普通陣列,如int[5],char[],double[]等
(2)。 型別是一個類,且滿足以下條件:
沒有使用者宣告的建構函式
沒有使用者提供的建構函式(允許顯示預置或棄置的建構函式)
沒有私有或保護的非靜態資料成員
沒有基類
沒有虛擬函式
沒有{}和=直接初始化的非靜態資料成員
沒有預設成員初始化器
struct A {
public:
A(int) {}
private:
A(const A&) {}
};
int main() {
A a(123);
A b = 123; // error
A c = { 123 };
A d{123}; // c++11
int e = {123};
int f{123}; // c++11
return 0;
}
我寫程式碼全蒙的。