2013-05-21 13 views
5

I pracy z C++ 11 i posiadają klasę zawierającą następujące struktury:Inicjalizacja struct zawierający const tablicę z listy inicjatora

struct Settings{ 
    const std::string name; 

    const std::string* A; 
    const size_t a; 
}; 

class X { 
    static const Settings s; 
    //More stuff 
}; 

W pliku .cpp Chcę określić to tak

X::s = {"MyName", {"one","two","three"}, 3}; 

Ale to nie działa. Jednak działa z użyciem zmiennej pośredniej. Czy istnieje sposób, aby to zrobić bez zmiennej pośredniej?

+3

Twój struct * nie zawiera * stałej tablicy. Zawiera wskaźnik do ciągu stałego. Mając to na uwadze, powinno być łatwo zrozumieć, dlaczego potrzebujesz "zmiennej pośredniej". – juanchopanza

+0

@juanchopanza: Cóż, chcę, żeby 'A' wskazywało (początek) stałą tablicę. Może to być również wskaźnik do 'const std :: string', ale nie tego chcę. Ale może nie rozumiem tego, na co się zwracasz ... – Haatschii

+1

@Haatschii: mylisz fakt, że tablica rozpada się na wskaźnik z myślą, że tablica i wskaźnik są identyczne. Pod względem semantyki języka tablica nie jest wskaźnikiem. Podobnie lista inicjalizacyjna nie jest tablicą. Kompilator może zainicjować tablicę z taką listą i może zepsuć tablicę do wskaźnika, ale nie wie w twoim przykładzie, aby przekształcić listę w tablicę, a następnie zepsuć ją do wskaźnika. Stąd potrzeba pośrednika, aby przekonwertować listę inicjalizującą na ciągłą tablicę przed przypisaniem do wskaźnika. –

Odpowiedz

5

Wskaźnik nie może zostać zainicjalizowany na podstawie listy wartości. Można użyć std::vector zamiast:

#include <vector> 

struct Settings{ 
    const std::string name; 
    const std::vector<std::string> A; 
//  ^^^^^^^^^^^^^^^^^^^^^^^^ 
    const size_t a; 
}; 

Następnie można napisać:

class X { 
    static const Settings s; 
    //More stuff 
}; 

const Settings X::s = {"MyName", {"one","two","three"}, 3}; 

Oto live example.

As suggested by Praetorian in the comments, może chcesz zastąpić std::vector z std::array, czy dopuszczalne jest, aby określić rozmiar kontenera jawnie, a jeśli rozmiar nie trzeba zmieniać w czasie wykonywania:

#include <array> 

struct Settings{ 
    const std::string name; 
    const std::array<std::string, 3> A; 
//  ^^^^^^^^^^^^^^^^^^^^^^^^^^ 
    const size_t a; 
}; 

A tutaj jest live example.

+1

Czy możesz wyjaśnić, dlaczego użycie wektora ma znaczenie? – taocp

+1

@taocp: Ponieważ nie można zainicjować wskaźnika za pomocą listy wartości. To, czego chcesz, to coś, co można zainicjować z listy inicjalizacyjnej: –

+3

Lub 'std :: array ' jeśli nie potrzebujesz, aby można było zmienić rozmiar. – Praetorian

5

Dzieje się tak, ponieważ przechowujesz wskaźnik do tablicy łańcuchów, a nie samych łańcuchów; więc potrzebujesz gdzieś łańcucha znaków do wskazania. Wszystko, co masz, to inicjator nawiasów klamrowych zawierający wskaźniki do tablic znaków.

Jeśli chcesz przechowywać same struny (na przykład w vector<string>), pierwsza wersja będzie działać.

Powiązane problemy