簡體   English   中英

為什么存在C ++ 11 std :: initializer_list構造函數重載規則?

[英]Why do the C++11 std::initializer_list constructor overloading rules exist?

我似乎無法想到也沒有找到以下代碼的理由:

std::vector<int> a{1,2} // calls (7)
std::vector<int> a(1,2) // calls (2)

// constructors from http://en.cppreference.com/w/cpp/container/vector/vector
vector( std::initializer_list<T> init, 
        const Allocator& alloc = Allocator() ); // (7)

explicit vector( size_type count, 
                 const T& value = T(),
                 const Allocator& alloc = Allocator()); // (2)

根據您使用的構造方法( {} vs () )調用不同的函數,這對我來說似乎非常不正常。 為什么std::initializer_list優先於其他函數,否則這些函數將完全匹配給定的參數? 我知道上面的構造函數2在C ++ 11中被棄用了,大概是因為這個改變,但我仍然不能解釋為什么會這樣 我可以看到這種行為的唯一好處是你可以初始化一個具有特定值的容器,只需要一對大括號; std::vector<int> a{1,2} vs std::vector<int> a{{1,2}} 但是,至少對我而言,這肯定不會超過這種模糊性以及對此所施加的重載決策的變化。 根據Scott Meyers的Effective Modern C ++, std::make_uniquestd::make_shared需要明確說明哪個表單用於構造作為其接口的一部分(因為重載解析)。 這對我來說似乎很荒謬。

我承認我必須遺漏一些東西,但我不確定它是什么 請注意,我剛剛使用std::vector作為示例,我一般都在詢問該功能。

這對C ++ 11來說非常有趣:原因是支撐的參數沒有類型。 但是有一個例外,它存在的原因對我來說並不清楚:“auto”變量是唯一允許將支持的參數隱式地作為初始化列表處理的變量。 但如果您有自動函數類型,則不允許返回此初始值設定項列表。

現在,您說得對:初始化列表的好處是您可以初始化具有特定值的容器。 這是一個值得改變的巨大好處!

在初始化列表之前,制作一個模板,允許您初始化具有不同值的容器內的每個類需要嚴格的解決方案,例如接收帶有每個值的std :: vector,或者構造一個“空”模板類,然后打孔每個值。

另一個原因是初始化列表允許您以比使用從C導入的這個可怕的<cstdarg>更安全的方式為C ++創建可變參數函數。(盡管可變參數模板在此上做得更好)

想要玩一點組合?

#include <iostream>
#include <vector>
#include <typeinfo>

using namespace std;


vector<int> func (const vector<int> &a) { //works
//auto func (const vector<int> &a) -> vector<int> { //works
//auto func (const vector<int> &a) { //don't even compile, "returns a initializer list" error
    for (int i: a) {
        cout << "My " << i << endl;
    }

    return {20 , 30};
}

int main()
{
    //play with anonymous functions
    auto y = [ ](vector<int> e) { return e; }; //works
    vector<int> x = y({20, 30});
    //auto y = [ ](){ return {20, 30}; }; //don't even compile, "returns a initializer list" error
    //vector<int> x = y();

    //play with initialization
    //vector<int> x = {2,2,20,30}; //works
    //vector<int> x{2,2,20,30}; //works
    //auto x = vector<int>{2,2,20,30}; //works
    //Bellow, a common mistake of people initializing a int to a auto, like auto x = { 1 }
    //auto x = {2,2,20,30}; //wrong, but compiles, its a initializer list
    //auto x{2,2,20,30}; //wrong, but compiles, its a initializer list

    //Play with return types
    //vector<int> x = func(vector<int>(2,2));  //works only with vector<int> and auto with trailing type
    //vector<int> x(func(vector<int>(2,2))); //works only with vector<int> and auto with trailing type
    //vector<int> x{func(vector<int>(2,2))}; //works only with vector<int> and auto with trailing type
    //auto x = func(vector<int>(2,2));  //works only with vector<int> and auto with trailing type
    //auto x(func(vector<int>(2,2))); //works only with vector<int> and auto with trailing type

    cout << typeid(x).name() << endl;
    for (int i: x) {
        cout << "My " << i << endl;
    }

    return 0;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM