Yapıcı başlatıcıda bir üye diziyi başlatma


100
class C 
{
public:
 C() : arr({1,2,3}) //doesn't compile
{}
    /*
    C() : arr{1,2,3} //doesn't compile either
{}
    */
private:
 int arr[3];
};

Bunun nedeninin dizilerin yalnızca =sözdizimi ile başlatılabileceğine inanıyorum , yani:

int arr[3] = {1,3,4};

Sorular

  1. Yapmak istediğim şeyi nasıl yapabilirim (yani, bir yapıcıda bir diziyi başlatmak (gövdeye eleman atamak değil)). Hatta mümkün mü?
  2. C ++ 03 standardı, ctor başlatıcılarda kümeleri (diziler dahil) başlatmakla ilgili özel bir şey söylüyor mu? Veya yukarıdaki kodun geçersizliği diğer bazı kuralların bir sonucu mu?
  3. C ++ 0x başlatıcı listeleri sorunu çözüyor mu?

PS Lütfen çok iyi bildiğim vektörlerden, boost :: array'lerden ve bunların dizilere üstünlüklerinden bahsetmeyin.


Yapıcılar sağlayan sabit boyutlu artırma dizilerinin varlığından da haberdar mısınız?
Benoît

2
@ Benoît: Ben. Ama düz dizileri bilmem gerekiyor :)
Armen Tsirunyan

Yanıtlar:


56
  1. Yapmak istediğim şeyi nasıl yapabilirim (yani, bir yapıcıda bir diziyi başlatmak (gövdeye eleman atamak değil)). Hatta mümkün mü?

Evet. Dizi içeren bir yapı kullanıyor. Bunu zaten bildiğini söylüyorsun, ama o zaman soruyu anlamıyorum. Bu şekilde, yapmak vücutta atamaları olmadan, yapıcı bir diziyi başlatmak. Bu ne boost::arrayyapar.

C ++ 03 standardı, ctor başlatıcılarda kümeleri (diziler dahil) başlatmakla ilgili özel bir şey söylüyor mu? Veya yukarıdaki kodun geçersizliği diğer bazı kuralların bir sonucu mu?

Bir mem-başlatıcı, doğrudan başlatma kullanır. Ve 8. maddenin kuralları bu tür şeyleri yasaklamaktadır. Aşağıdaki durumdan tam olarak emin değilim, ancak bazı derleyiciler buna izin veriyor.

struct A {
  char foo[6];
  A():foo("hello") { } /* valid? */
};

Daha fazla ayrıntı için bu GCC PR'ye bakın.

C ++ 0x başlatıcı listeleri sorunu çözüyor mu?

Evet onlar yapar. Ancak söz diziminiz geçersiz sanırım. Liste başlatmayı başlatmak için doğrudan parantez kullanmanız gerekir

struct A {
  int foo[3];
  A():foo{1, 2, 3} { }
  A():foo({1, 2, 3}) { } /* invalid */
};

Bunu yazdığımda tökezledim: char * const foo[6];sınıf üyesi. Bu gerektirir 11 C ++ derlemeye başlatıcı.
JATothrim

33

C ++ 98, diziyi sıfırlamaktan (veya POD olmayan öğeler için değer başlatmadan) başka hiçbir şey için doğrudan bir sözdizimi sağlamaz. Bunun için sadece yazın C(): arr() {}.

Roger Pate'in C ++ 0x toplu başlatmanın iddia edilen sınırlamaları hakkında yanlış olduğunu düşünüyorum, ancak ona bakmak veya kontrol etmek için çok tembelim ve önemli değil, değil mi? DÜZENLEME : Roger "C ++ 03" hakkında konuşuyordu, "C ++ 0x" olarak yanlış okudum. Üzgünüm Roger. ☺

Geçerli kodunuz için bir C ++ 98 geçici çözümü, diziyi a dizisine sarmak ve structbu türdeki statik bir sabitten başlatmaktır. Veriler zaten bir yerde bulunmalıdır. Manşetten şu şekilde görünebilir:

class C 
{
public:
    C() : arr( arrData ) {}

private:
     struct Arr{ int elem[3]; };
     Arr arr;
     static Arr const arrData;
};

C::Arr const C::arrData = {{1, 2, 3}};

0x'in sahip olduğunu söylemiştim.

@Roger: "agrregate başlatma ... ctor başlatıcıya uymuyor". Bir mem-başlatıcının sözdizimi olan C ++ 0x taslak N3126'nın §12.5.2 / 1'deki sözdizimi, parantezli bir başlangıç ​​listesi kullanmayı içerir .
Şerefe ve hth. - Alf

6
Cümlenin ilk iki kelimesi C ++ 03'te ...

8

Çözüm:

template<class T, size_t N>
struct simple_array { // like std::array in C++0x
   T arr[N];
};


class C : private simple_array<int, 3> 
{
      static simple_array<int, 3> myarr() {
           simple_array<int, 3> arr = {1,2,3};
           return arr;
      }
public:
      C() : simple_array<int, 3>(myarr()) {}
};

3
  1. Hayır, maalesef.
  2. Dilbilgisi tarafından izin verilmediğinden (daha fazlası aşağıda) istediğiniz şekilde yapamazsınız. Yalnızca ctor benzeri başlatma kullanabilirsiniz ve bildiğiniz gibi bu, dizilerdeki her bir öğeyi başlatmak için kullanılamaz.
  3. Buna inanıyorum, çünkü başlatmayı birçok yararlı yolla tahtaya genelliyorlar. Ama ayrıntılardan emin değilim.

C ++ 03'te, toplu başlatma yalnızca aşağıdaki sözdizimine benzer, ayrı bir ifade olması gereken ve bir ctor başlatıcısına sığmayan sözdizimi için geçerlidir.

T var = {...};

2

Ne dersin

...
  C() : arr{ {1,2,3} }
{}
...

?

G ++ 4.8 üzerinde iyi derler


Bu standart mı? İlgili maddeyi aktarır mısınız lütfen?
Armen Tsirunyan

2
Visual C ++ üzerinde derlemez.
sergiol

-3

Yapıcınızda bir dizi init mi başlatmak istiyorsunuz? Statik bir diziye yönlendirin.

class C 
{
public:
    int *cArray;

};

C::C {
    static int c_init[]{1,2,3};
    cArray = c_init;
}

2
Bu kötü bir fikir çünkü o diziyi değiştirirseniz, o sınıfın tüm örnekleri için değişir.
morty
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.