2009-04-15 14 views
13

In dem folgenden Code möchte ich Array als ein Array der Größe X definiert werden, wenn der Klassenkonstruktor aufgerufen wird. Wie kann ich das machen?Ermitteln Array-Größe in Konstruktor Initialisierer

class Class 
{ 
public: 
    int array[]; 
    Class(int x) : ??? { } 
} 
+1

I Wenn Sie C++ regelmäßig verwenden möchten, empfehle ich Ihnen dringend, sich mit der Standardvorlagenbibliothek vertraut zu machen. Es erleichtert das Arbeiten mit Datensammlungen * viel *. – Brian

+1

Nebenbei, Vektoren machen es relativ einfach, mit dem Array zu arbeiten, ohne die Größe im Voraus zu kennen. Es ist nicht notwendig, die Größe im Voraus zu wissen; Sie können Elemente am Ende eines Vektors in (amortisierter) O (1) -Zeit mit push_back anhängen. – Brian

+0

Die Verwendung von Vektoren bringt neue Probleme, da die Klasse, die ich zu vektorisieren versuche, "neue" Operatoren geschützt hat. Aber das war nicht das, was ich gefragt habe, also vergiss es. – zaratustra

Antwort

17

Sie können nicht die Größe eines Arrays mit einer nicht-const Dimension initialisieren, die (in der aktuellen C++ Standard, zumindest nicht AFAIK) nicht zum Zeitpunkt der Kompilierung berechnet werden.

Ich empfehle die Verwendung std::vector<int> anstelle von Array. Es bietet Array-ähnliche Syntax für die meisten Operationen.

+0

Wie wäre die Syntax für die Verwendung eines Vektors in dieser Situation? – zaratustra

+2

Vektor < int > Array; Klasse (x): Array (x) {}; – DevSolar

1

Anstatt ein RAW-Array zu verwenden, verwenden Sie stattdessen einen Vektor.

class SomeType { 
    vector<int> v; 
    SomeType(size_t x): v(x) {} 
}; 

unter Verwendung eines Vektors erhalten Sie automatische Leckschutz im Gesicht einer Ausnahme und viele andere Vorteile gegenüber einem rohen Array.

+0

Meinst du "die Verwendung von * einem Vektor * gibt Ihnen automatischen Leckschutz"? :) – mkb

+0

@mkb, das ist zweimal heute habe ich grundsätzlich dumme Kommentare gemacht. Müssen mehr Kaffee trinken, um aufzuwachen, bevor ich mit der Veröffentlichung beginne;) – JaredPar

11

den neuen Betreiber Verwendung:

class Class 
{ 
    int* array; 
    Class(int x) : array(new int[x]) {}; 
}; 
+3

Vergessen Sie nicht, delete [] im Konstruktor aufzurufen, wenn Sie diesen Code verwenden. – Brian

+7

Wenn Sie dies tun, benötigen Sie auch einen Kopierkonstruktor, einen Zuweisungsoperator und einen Destruktor. Wenn Sie einen std :: vector verwenden, erhalten Sie genau die gleiche Funktionalität, benötigen jedoch keine dieser Funktionen. –

+0

+1 Dies beantwortet die Frage des OP tatsächlich, indem es die Größe eines Arrays initialisiert, obwohl es tatsächlich "int * array" ersetzt, das kein Array ist, mit der Liste im Konstruktor. @ (anon) neben einem Kopierkonstruktor, einem Zuweisungsoperator und einem Destruktor, beantwortet dies wirklich die Frage. –

0

Sie es nicht in C++ tun - verwenden, um ein std :: vector statt:

#include <vector> 

struct A { 
    std::vector <int> vec; 
    A(int size) : vec(size) { 
    } 
}; 
0

Ihr Array deklarieren als Zeiger. Sie können ihn später in der Initialisierungsliste durch new initialisieren.

Besser, Vektor für unbekannte Größe zu verwenden.

Sie könnten sich auch this question auf Arrays mit variabler Länge ansehen.

+0

besser, um den Vektor für bekannte Größe zu verwenden –

+0

müssen darüber einig sein – Shree

+0

BAD Idee. Die Speicherverwaltung für einen Zeiger, der wie ein Array funktioniert, ist bei Vorhandensein von Ausnahmen nicht trivial. Verwenden Sie std :: vector oder std :: tr1 :: array. –

3

Ich glaube nicht, dass es getan werden kann. Zumindest nicht so, wie du es willst. Sie können ein Array mit statischer Größe (Array []) nicht erstellen, wenn die Größe aus dynamischen Informationen (x) stammt.

Sie müssen entweder einen Zeiger auf int und die Größe speichern und den Kopierkonstruktor, den Zuweisungsoperator und den Destruktor überlasten, um damit umzugehen, oder verwenden Sie std :: vector.

class Class 
{ 
    ::std::vector<int> array; 
    Class(int x) : array(x) { } 
}; 
0

zwei Optionen:

Verwendung std :: vector. Dies ermöglicht eine einfache Größenanpassung des Arrays.
Verwenden Sie std :: tr1 :: array. Dies hat eine statische Größe.

Beide können korrekt in der Initialisiererliste des Konstruktors initialisiert werden.

4

Verstehst du nicht, dass es nicht notwendig ist, Vektor zu verwenden, wenn man Arrays verwenden will, ist es eine Frage der Effizienz, z. weniger Platz, keine Kopierzeit (in diesem Fall muss, wenn es richtig gehandhabt wird, nicht einmal das Array innerhalb eines Destruktors gelöscht werden), aus welchen Gründen auch immer.

die richtige Antwort ist: (zitiert)

class Class 
{ 
    int* array; 
    Class(int x) : array(new int[x]) {}; 
}; 

Versuchen Sie nicht, eine zu zwingen, nicht optimale Alternativen zu verwenden, oder Sie werden verwirrend unerfahrene Programmierer sein

3

Sorry für necroing diesen alten Thread. Es gibt tatsächlich eine Möglichkeit, die Größe der Kompilierzeit des Arrays herauszufinden.Es geht ungefähr so:

#include <cstdlib> 

template<typename T> 
    class Class 
    { 
     T* _Buffer; 

     public: 
     template<size_t SIZE> 
      Class(T (&static_array)[SIZE]) 
      { 
       _Buffer = (T*)malloc(sizeof(T) * SIZE); 

       memcpy(_Buffer, static_array, sizeof(T) * SIZE); 
      } 

      ~Class() 
      { 
       if(_Buffer) 
       { 
        free(_Buffer); 
        _Buffer = NULL; 
       } 
      } 
    }; 

int main() 
{ 
    int int_array[32]; 
    Class<int> c = Class<int>(int_array); 

    return 0; 
} 

Alternativ, wenn Sie hassen/neu malloc, dann können Sie stattdessen eine Größe Templat-Klasse erstellen. Allerdings würde ich es nicht wirklich empfehlen und die Syntax ist ziemlich hässlich.

#include <cstdio> 

template<typename T, size_t SIZE> 
    class Class 
    { 
     private: 
      T _Array[sz]; 
     public: 
      Class(T (&static_array)[SIZE]) 
      { 
       memcpy(_Array, static_array, sizeof(T) * SIZE); 
      } 
    }; 

int main() 
{ 
    char int_array[32]; 
    Class<char, sizeof(int_array)> c = Class<char, sizeof(int_array)>(int_array); 
    return 0; 
} 

Anyways, ich hoffe, dass dies hilfreich war :)

+2

sind Sie ein Assistent – zaratustra

+0

In C++ 11 eine bessere Methode zum Ermitteln der Größe eines integrierten Arrays ist eine constexpr-Vorlage-Funktion. Zum Beispiel: Vorlage Constexpr Std :: Größe_t Größe (const T (& Array) [N]) { zurück N; } – Ricky65

25

Sie Leute diese so kompliziert sind. Natürlich können Sie dies in C++ tun. Es ist in Ordnung für ihn, ein normales Array für Effizienz zu verwenden. Ein Vektor macht nur Sinn, wenn er die endgültige Größe des Arrays nicht im Voraus kennt, d. H. Er muss im Laufe der Zeit wachsen.

Wenn Sie die Array-Größe eine Ebene höher in der Kette wissen können, eine Templat-Klasse ist die einfachste, weil es keine dynamische Zuweisung ist und keine Chance auf Speicherleck:

template < int ARRAY_LEN > // you can even set to a default value here of C++'11 

class MyClass 
    { 
    int array[ARRAY_LEN]; // Don't need to alloc or dealloc in structure! Works like you imagine! 
    } 

// Then you set the length of each object where you declare the object, e.g. 

MyClass<1024> instance; // But only works for constant values, i.e. known to compiler 

Wenn Sie nicht wissen, die Länge an der Stelle, an der Sie das Objekt deklarieren, oder wenn Sie dasselbe Objekt mit unterschiedlichen Längen wiederverwenden wollen, oder Sie müssen eine unbekannte Länge akzeptieren, dann müssen Sie es in Ihrem Konstruktor zuweisen und es in Ihrem Destruktor freigeben ... (und in der Theorie immer überprüfen, um sicherzustellen, dass es funktioniert ...)

class MyClass 
    { 
    int *array; 

    MyClass(int len) { array = calloc(sizeof(int), len); assert(array); } 
    ~MyClass() { free(array); array = NULL; } // DON'T FORGET TO FREE UP SPACE! 
    } 
Verwandte Themen