2017-08-28 28 views
6

我最近正在研究一個C++項目,並遇到了一個我不能完全理解的字符串構造函數的邊界案例。相關的代碼(其you can run here)如下:爲什麼此代碼將字符串初始化爲單個字符時調用initializer_list構造函數?

#include <iostream> 
#include <string> 
using namespace std; 

int main() { 
    string directParens(1, '*'); 
    string directBraces{1, '*'}; 
    string indirectBraces = {1, '*'}; 

    cout << directParens.size() << endl; // 1 
    cout << directBraces.size() << endl; // 2 
    cout << indirectBraces.size() << endl; // 2 
    return 0; 
} 

琴絃的支架初始化版本最終不得不在他們的兩個字符,即,具有數值1 char後跟一個星。

我不明白爲什麼字符串的大括號初始化版本調用initializer_list構造函數而不是構造函數需要大小和字符。該initializer_list構造有這樣的簽名:

basic_string(std::initializer_list<CharT> init, 
      const Allocator& alloc = Allocator()); 

鑑於stringbasic_string字符的別名,具體的簽名會

string(std::initializer_list<char> init, 
     const Allocator& alloc = Allocator()); 

如何初始化{1, '*'},其中包含的元素int類型都和類型爲char,與此構造函數匹配?我的印象是,std::initializer_list中的所有文字必須具有相同的字體 - 這是不正確的嗎?

+1

請注意,縮小轉換有一個例外[對於常量表達式,其轉換後的結果將符合目標類型](https://stackoverflow.com/a/26974911/1708801) –

回答

15

初始值設定項{1,'*'}如何與此構造函數匹配,包含int類型和char類型的元素?

由於字面1和字符'*'兩者都轉換爲char不使用收縮轉換。因此,他們有資格撥打initializer_list<char>構造函數。和initializer_list構造函數總是使用列表初始化時有優先權。如果可以從參數調用initializer_list構造函數,那麼它將會。

切勿使用支撐-INIT-名單與除非你打算在列表中的元素容器元素的容器的。如果你打算將它們作爲構造函數參數,則使用構造函數。

+0

啊,呃。因此,如果所有元素都可以轉換爲基礎類型而不縮小轉換,則大括號初始化器將被解釋爲initializer_list。爲了確認,這是否意味着{3,3.0}可以被解釋爲initializer_list ,但不是initializer_list ?而且{INT_MAX,'*'}可能是一個初始化表列表? – templatetypedef

+0

@templatetypedef:那麼,'{INT_MAX,'*'}'示例*不能*爲'initializer_list ',因爲'INT_MAX'不能在沒有縮小轉換的情況下轉換爲'char'。但除此之外,你是對的。 –

+0

哦,我認爲縮小轉換適用於*類型*,而不是*值。*清除了一些東西!謝謝! – templatetypedef

相關問題