新的語言特性,Lambda函式,Lambda函式,返回類型函式,其它類型推斷,constexpr限制,變數模板,聚合初始化,一維長度數組,二進制字面值,新標準庫特性,共享和互斥,Optional值,異構查找,標準字面值,定長數組容器,定址多元組,其它函式特性,
新的語言特性
以下為是C++14中被加入語言核心的特性。
Lambda函式
在C++11中,
lambda函式參數需要被聲明為具體的類型。C++14放寬了這一要求,允許lambda函式參數類型使用類型說明符auto。
auto lambda = [] (auto x, auto y) {return (x + y); }
儘管使用了C++11的關鍵字auto,泛型Lambda函式並不遵循auto類型推導的句法,而是遵循模板參數推導的規則(它們相似,但並不是在所有情況下都是相同的)。以上代碼與下面的等價:
struct unnamed_lambda
{
template <typename T,typename U>
auto operator()(T x, U y) const
{
return (x+y);
}
};
auto lambda = unnamed_lambda();
Lambda函式
C++11的lambda函式通過值拷貝或引用捕獲在外層作用域聲明的變數。這意味著lambda的值成員不可以是只能move的類型。 C++14允許被捕獲的成員用任意的表達式初始化。這既允許了通過move捕獲,也允許了任意聲明lambda的成員,而不需要外層作用域有一個具有相應名字的變數。
這是通過使用一個初始化表達式完成的:
auto lambda=[value{1}] { return value; }
lambda函式 lambda 會返回1,因為value被初始化為1。被聲明的捕獲變數的類型以與auto相同的方式,根據初始化表達式推斷。
使用標準函式std::move可以使之被用以通過move捕獲:
auto ptr=std::make_unique<int>(10);//See below for std::make_unique
auto lambda=[ptr{std::move(ptr)}] { return(*ptr); }
聲明ptr{std::move(ptr)}使用了兩次ptr。第一次使用聲明了一個新的變數,但由C++的作用域規則,在初始化表達式求值完畢之前,該變數不在作用域內。所以第二個ptr表示之前在lambda之外聲明的變數。
返回類型函式
C++11允許lambda函式根據return語句的表達式類型推斷返回類型。C++14為所有的函式提供了這個能力。C++14還拓展了原有的規則,使得函式體並不是return expression;形式的函式也可以使用返回類型推導。
為了誘發返回類型推導,函式聲明必須將auto作為返回類型,但沒有C++11的後置返回類型說明符:
auto DeduceReturnType(); //Return type to be determined.
如果函式實現中含有多個return表達式,這些表達式必須可以推斷為相同的類型。
使用返回類型推導的函式可以被前向聲明,但在定義之前不可以使用。它們的定義在使用它們的翻譯單元之中必須是可用的。
這樣的函式中可以存在
遞歸,但遞歸調用必須在函式定義中的至少一個return語句之後,例如:
auto Correct(int i)
{
if (i == 1)
return (i); // return type deduced as int
else
return (Correct(i-1)+i); // OK to call it now
}
但是下面這樣寫是錯誤的:
auto Wrong(int i)
{
if(i!=1)
return (Wrong(i - 1) + i); // Too soon to call this. No prior return statement.
else
return i; // return type deduced as int
}
其它類型推斷
C++11中增加了兩種推斷類型的方式。auto根據給出的表達式產生具有合適類型的變數。
decltype可以計算給出的表達式的類型。但是,decltype和auto推斷類型的方式是不同的。特別是,auto總是推斷出非引用類型,就好像使用了std::remove_reference一樣,而auto&&總是推斷出引用類型。然而decltype可以根據表達式的結果類別和表達式的性質推斷出引用或非引用類型:
int i;
int &&f();
auto x3a = i; // decltype(x3a) is int
decltype(i) x3d = i; // decltype(x3d) is int
autox 4a = i; // decltype(x4a) is int
decltype((i)) x4d=(i); //decltype(x4d) is int&
auto x5a = f(); //decltype(x5a) is int
decltype(f()) x5d =f(); // decltype(x5d) is int&&
C++14將增加decltype(auto)的語法。這將允許auto聲明使用decltype對於給定表達式的推斷規則。
decltype(auto)的語法也可以用於返回類型推導,只需使用decltype(auto)代替auto來誘發。
constexpr限制
C++11引入了constexpr函式的概念,這樣的函式可以在編譯期執行。它們的返回值可以通過計算所需的常量表達式(如整型的模板參數)得出。然而C++11要求constexpr函式只含有一個將被返回的表達式(也可以還含有static_assert聲明等其它語句,但允許的語句類型很少)。
C++14將放鬆這些限制。constexpr函式將可以含有以下內容:
任何聲明,除了:
static或thread_local變數。
沒有初始化的變數聲明。
條件分支語句if和switch。goto是不允許的。
所有的循環語句,包括基於範圍的for循環。
表達式可以改變一個對象的值,如果該對象的生命期在常量表達式函式內開始。包括對有constexpr聲明的任何非const非靜態成員函式的調用。
對於調用非constexpr函式的限制仍然存在。所以如果使用基於範圍的for循環,begin和end的重載必須自身是constexpr。值得注意的是,std::initializer_list在本地和全局都具有constexpr聲明的begin/end函式。
此外,C++11指出,所有被聲明為constexpr的非靜態成員函式也隱含聲明為const(即函式不能修改*this的值)。這點已經被刪除,非靜態成員函式可以為非const。然而,只有當對象的生命期在常量表達式求值中開始,非const的constexpr成員函式才可以修改類成員。
變數模板
在
C++之前的版本中,模板可以是
函式模板或
類模板。C++14還也可以創建變數模板。模板的一般規則,包括特化都適用於變數模板的聲明和定義。
聚合初始化
C++11新增類內成員默認初始值,這是一個表達式,被套用到類作用域的成員上,如果構造函式沒有初始化這個成員。聚合體的定義被改為明確排除任何含有類內成員默認初始值的類,因此,他們不允許使用聚合初始化。
C++14將放鬆這一限制,這種類型也允許聚合初始化。如果花括弧初始化列表不提供該參數的值,類內成員默認初始值會初始化它。
一維長度數組
在
C++11和之前的標準中,在堆疊上分配的數組被限制為擁有一個固定的、編譯期確定的長度。C++14允許在堆疊上分配的一個數組的最後一維具有運行期確定的長度。
運行期確定長度的數組不可以作為對象的一部分,也不可以具有全局存儲期,他們只能被聲明為局部變數。運行期確定長度的數組也可以使用C++11的基於範圍的for循環。
二進制字面值
新標準庫特性
共享和互斥
Optional值
C++14增加了一個optional類型,其值可能存在或不存在。這一類型基於
Boost的boost::optional類,而添加了C++11和C++14中的新特性,諸如移動和in-place構造。它不允許用在引用類型上。類被專門的設計為一個literal type(如果模板參數本身是一個literal type),因此,在必要的情況下含有constexpr構造函式。
異構查找
C++標準庫定義了四個關聯容器類。set和multiset允許使用者根據一個值在容器中查找對應的的同類型的值。map和multimap容器允許使用者指定鍵(key)和值(value)的類型,根據鍵進行查找並返回對應的值。然而,查找只能接受指定類型的參數,在map和multimap中是鍵的類型,而在set和multiset容器中就是值本身的類型。
C++14允許通過其他類型進行查找,只需要這個類型和實際的鍵類型之間可以進行比較操作。在operator<被重載的情況下,這允許一個鍵為std::string的map與一個鍵為const char* 的map進行比較。
為保證向後兼容性,這種異構查找只在相應關聯容器的比較運算符允許的情況下有效。標準庫類 std::less(set和map到默認比較算符)與std::greater也可以被用來進行異構查找。
標準字面值
C++11定義了自定義字面值的語法,但標準庫沒有使用其中的任何一個。C++14增加了以下標準字面值:
兩個"s"互不干擾,因為表示字元串的只能對字元串字面值操作,而表示秒的只針對數字。
定長數組容器
std::vector類型表示一個可變長度的數組,可以根據需要增長和收縮。C++11的std::array表示一個固定長度的數組,其長度在編譯時確定。
C + +14將添加std::dynarray類型,它代表一個固定長度的數組,其大小在運行期構造對象時確定。std::dynarray類被明顯地設計為當它被放置在棧上時(直接放置在棧上,或作為另一個棧對象的成員),可以使用棧記憶體而不是
堆記憶體。
定址多元組
C++11引入的std::tuple類型允許不同類型的值的聚合體用編譯期整型常數索引。C++14還允許使用類型代替常數索引,從多元組中獲取對象。若多元組含有多於一個這個類型的對象,將會產生一個編譯錯誤:
tuple <string, string, int> t ("foo", "bar", 7);
int i = get<int>(t); // i == 7
int j = get<2>(t); // Same as before: j == 7
string s = get<string>(t); // Compiler error due to ambiguity
其它函式特性
std::make_unique可以像 std::make_shared一樣使用,用於產生std::unique_ptr對象。
std::integral_constant將會具有一個返回常量值的operator()重載。
全局std::begin/std::end函式之外,將會增加std::cbegin/std::cend函式,它們返回一個範圍的開始/結束常量
疊代器。