Fark

2014-10-03 31 views
7

Bu C++ 11 kod benim için çalışıyor listelenmektedir:Fark

#include <iostream> 
#include <vector> 
#include <array> 
using namespace std; 

struct str { 
    int first, last; 
}; 


vector<str> fields { 
    {1,2}, {3,4}, {5,6} 
}; 

int main() 
{ 
    for (str s : fields) 
     cout << s.first << " " << s.last << endl; 
} 

altı beklenen değerleri yazdırır.

Ancak vector<str> değerini array<str,3> olarak değiştirirseniz, gcc bana şu hatayı verir: "std :: array" için çok fazla başlatıcı. "

Ben böylece fields başlatılması değiştirirseniz:

array<str,3> fields { 
    str{1,2}, str{3,4}, str{5,6} 
}; 

şeyler güzel çalışır.

Peki neden std::array kullanırken str{1,2} ihtiyacım var ama sadece {1,2} std::vector kullanırken?

cevap

6

aggregate initialization adresindeki cppreference bölümlerine bakın.

The effects of aggregate initialization are:

  • Each array element or non-static class member, in order of array subscript/appearance in the class definition, is copy-initialized from the corresponding clause of the initializer list.

  • If the initializer clause is a nested braced-init-list, the corresponding class member is itself an aggregate: aggregate initialization is recursive.

Bu demektir ki gibi sizin yapı içindeki bir toplamını olsaydı:

struct str { 
    struct asdf 
    { 
     int first, last; 
    } asdf; 
}; 

asdf yani { { 1, 2 } }, ilk iç içe ayracı-init-listesi tarafından ilklenir. Genelde iki çift köşeli ayrata ihtiyacınız olmasının nedeni, iç içe geçmiş küme başlangıç ​​listesi std::array (örneğin, T a[N]) içinde temel kümeyi başlatmasıdır.

array<str,3> fields { 
    1, 2, 3, 4, 5, 6 
}; 

ya:

Ancak, yine de bu gibi dizi sunabilmesi

array<str,3> fields { { 
    1, 2, 3, 4, 5, 6 
} }; 

yerine.

Diğer yandan, vektörünüzü nasıl başlattığınız list initialization kapsamındadır. std::vector, std::initializer_list kabul eden bir kurucuya sahiptir.

vector<str> fields { 
    1,2, 3,4, 5,6 
}; 

ama: Eğer böyle (vektör başlatılamadı mümkün olmaz

The effects of list initialization of an object of type T are:

  • Otherwise, the constructors of T are considered, in two phases:

    • All constructors that take std::initializer_list as the only argument, or as the first argument if the remaining arguments have default values, are examined, and matched by overload resolution against a single argument of type std::initializer_list

Not.

vector<int> fields { 
    1,2, 3,4, 5,6 
}; 

gayet olumlu

4

Bu, dizinin ilklendirmesi vektörden biraz farklı oluşturulduğundan.
Bir diziyi başlatmak için iki parantez kullanmanız gerekir.
Bir sözdizimi özelliği nedeniyle, yalnızca bir nesneyi başlatırsanız atlayabilirsiniz.

array{1,2,3} -> array{{1,2,3}} 

Fakat derleyici ek parantez eklemez böylece örnekte birden fazla nesne başlatmak:
Yani aşağıdaki ok. İki parantez kullanarak bunu düzeltin.

array<str,3> fields {{ 
    {1,2}, {3,4}, {5,6} 
}};