wie man ein Array von Objekten dynamisch mit einem Konstruktor in C++ deklariert
Lesezeit: 5 Minuten
Benutzer972276
Ich habe mich gefragt, ob es möglich ist, ein Array von Objekten zu erstellen, wenn das Objekt Dinge für den Konstruktor übergeben muss. Ich möchte so etwas:
MyClass *myVar;
myVar = new MyClass[num]; // I would like to specify the array size after declaration
int i = 0;
for(i = 0;i < num;i++)
myVar[i] = new MyClass(0,0); // I would also like to populate the array with new objects
Ich weiß, dass das funktioniert:
MyClass *myVar;
myVar = new MyClass[num];
aber das funktioniert nur, wenn dem Konstruktor nichts übergeben wurde. Ist das, was ich versuche, möglich? Wenn ja, wie mache ich das?
BEARBEITEN: Ich habe herausgefunden, wie man es mit Arrays macht. So habe ich es gemacht:
MyClass **myVar;
myVar = new MyClass *[num];
for(i = 0;i < num;i++)
myVar[0] = new MyClass(0,0);
Ich würde Vektoren und dergleichen verwenden, aber mein Lehrer hat uns gesagt, dass wir, wann immer möglich, einfache Arrays verwenden sollen. Die obige Lösung habe ich tatsächlich von einem Code erhalten, den mein Lehrer geschrieben hat. Vielen Dank für Ihre Hilfe!
Später Kommentar, aber für jeden, der darauf stößt, glaube ich, dass es so sein sollte myVar[i] = new myClass(0, 0) nicht myVar[0]
– Connor Fuhrmann
1. Dezember 21 um 1:25 Uhr
Nawaz
MyClass *myVar;
myVar = new MyClass[num];
Tatsächlich können Sie in dieser Form keinen Konstruktor aufrufen, der Parameter akzeptiert. Dies ist laut Sprachspezifikation nicht zulässig.
Allerdings, wenn Sie verwenden std::vectordie ich Ihnen empfehle zu verwenden, dann können Sie einen Vektor erstellen, der einen nicht standardmäßigen Konstruktor aufruft als:
#include <vector> //header file where std::vector is defined
std::vector<MyClass> arr(num, MyClass(10,20));
Es erstellt einen Vektor von num Elemente, jedes Element wird erstellt, indem der Kopierkonstruktor der Klasse aufgerufen und übergeben wird MyClass(10,20) als Argument dazu.
Der Vektor ist auch gut, weil Sie den Speicher jetzt nicht mehr selbst verwalten müssen. Weder manuelle Zuordnung noch manuelle Freigabe. Außerdem können Sie die Anzahl der Elemente durch einen Anruf erfahren arr.size() Jederzeit. Sie wissen immer, wie viele Elemente der Vektor enthält. Sie können auch jederzeit Elemente hinzufügen, indem Sie einfach anrufen .push_back() Mitgliedsfunktion als:
arr.push_back(MyClass(20,30));
Und jetzt können Sie auf Elemente zugreifen, genau wie Sie auf Arrays zugreifen, dh indem Sie index verwenden:
f(arr[i]); // 0 <= i < arr.size();
Darüber hinaus können Sie Iteratoren verwenden, die die idiomatische Programmierung erleichtern und es Ihnen ermöglichen, verschiedene algorithmische Funktionen von zu verwenden <algorithm> Überschrift als:
#include <algorithm> //header file where std::for_each is defined
std::for_each(arr.begin(), arr.end(), f);
wo f ist eine Funktion, die ein Argument des Typs annimmt MyClass& (oder MyClass const &) je nachdem, was Sie tun möchten f.
In C++11 können Sie Lambda wie folgt verwenden:
std::for_each(arr.begin(), arr.end(), [](const MyClass & m)
{
//working with m
});
Danke für deine Hilfe! Eigentlich suchte ich nach einem Ansatz, der Arrays anstelle von Vektoren verwendet, weil mein Lehrer wollte, dass die Klasse stattdessen Arrays verwendet. Ich habe die Antwort aber gefunden.
– Benutzer972276
11. Dezember 11 um 9:33 Uhr
@ user972276: Für Arrays ist Ihr erster Ansatz, was man tun kann, wenn Sie einen nicht standardmäßigen Konstruktor aufrufen möchten. Wenn Sie jedoch in Zukunft jemals ein Array benötigen, Erste erwägen zu verwenden std::vector. Es ist ein großartiger Container mit vielen coolen Funktionen.
– Nawaz
11. Dezember 11 um 9:35 Uhr
In C++0x funktioniert diese Grammatik, die den nicht standardmäßigen Konstruktor in einem neuen Ausdruck aufrufen kann:
MyClass *myVar;
myVar = new MyClass[2]{{10, 20},{20, 30}};
Aber ich bezweifle, ob es funktioniert, wenn die Anzahl der Elemente nur zur Laufzeit verfügbar ist.
Der Vektoransatz wäre besser, wie in Nawaz ‘Antwort gezeigt.
Connor Farell
Zeiger auf Zeiger ist äquivalent zu 1. Array von Zeigern und 2. Vektor Vektor von Zeigern. Eine Möglichkeit, die ich in der Vergangenheit getan habe, ist die Verwendung eines Doppelzeigers. Dieser Ansatz eliminiert den Overhead der Vektordatenstruktur und es wird eine bevorzugte Speichereffizienz benötigt.
MyClass ** myvar;
myvar = new Myclass*[num]
for(int i = 0; i < num; i++){
*(myvar+i) = new Myclass(i);}
Funktioniert mit so ziemlich jeder Kontrollstruktur, die Sie sich vorstellen können. Der Nachteil ist, dass die Speicherzuweisung nicht zusammenhängend ist und meine Geschwindigkeit für eine große Anzahl von num beeinträchtigt wird.
Dies ähnelt dem vector-Ansatz, nur dass Sie die Details selbst verwalten. Scheint die beste Lösung zu sein, wenn Sie die Overhead-Kosten des Vektors nicht wollen.
– Kemin Zhou
28. September 2020 um 20:41 Uhr
Sie können auch so etwas tun:
MyClass *myVar[num];
for(int i = 0; i < num; i += 1)
{
myVar[i] = new MyClass(0, 0);
}
Tatsächlich können Sie ein Placement new verwenden, um dies zu handhaben:
MyClass * myVar;
myVar = reinterpret_cast<MyClass *>(new char[num * sizeof(MyClass)]);
int i = 0;
for (i = 0; i < num; i++) {
new(&myVar[i]) MyClass(0,0);
}
Du solltest benutzen std::aligned_storage anstatt new char[].
– MM
24. Juni 15 um 15:06 Uhr
Es sollte auch erwähnt werden, dass Sie, um diesen Speicher freizugeben, die Destruktoren jedes Objekts durchlaufen und aufrufen und dann aufrufen müssen delete[] reinterpret_cast<char *>(myVar); .
– MM
24. Juni 15 um 15:07 Uhr
amiralwaled
Die Antwort von @Nawaz ist wirklich gut in der Verwendung von Vektoren, hat aber bei mir nicht funktioniert, da sie Vektoren derselben Objekte erstellt (alle verweisen auf dasselbe Objekt).
class Graph
{
public:
Graph(long V); // none default Constructor
}
std::vector<Graph> myGraph;
for (int i = 0; i < T; i++) // read all graphs
{
Graph newGraph(N);
myGraph.push_back(newGraph);
}
Du solltest benutzen std::aligned_storage anstatt new char[].
– MM
24. Juni 15 um 15:06 Uhr
Es sollte auch erwähnt werden, dass Sie, um diesen Speicher freizugeben, die Destruktoren jedes Objekts durchlaufen und aufrufen und dann aufrufen müssen delete[] reinterpret_cast<char *>(myVar); .
– MM
24. Juni 15 um 15:07 Uhr
.
7582800cookie-checkwie man ein Array von Objekten dynamisch mit einem Konstruktor in C++ deklariertyes
Später Kommentar, aber für jeden, der darauf stößt, glaube ich, dass es so sein sollte
myVar[i] = new myClass(0, 0)
nichtmyVar[0]
– Connor Fuhrmann
1. Dezember 21 um 1:25 Uhr