Was ist der billigste Weg, um ein std::vector
Array aus einem C-Stil zu initialisieren ?
Beispiel: In der folgenden Klasse habe ich eine vector
, aber aufgrund externer Einschränkungen werden die Daten als Array im C-Stil übergeben:
class Foo {
std::vector<double> w_;
public:
void set_data(double* w, int len){
// how to cheaply initialize the std::vector?
}
Natürlich kann ich w_.resize()
die Elemente aufrufen und dann durchlaufen oder aufrufen std::copy()
. Gibt es bessere Methoden?
Antworten:
Vergessen Sie nicht, dass Sie Zeiger als Iteratoren behandeln können:
quelle
assign
sicherlich zur Optimierung verwenden. Zumindest in VC ++ macht es genau das.v.end()
ein Iterator, der in einem ähnlichen Fall eines nach dem Ende mit einem Vektor zeigt). Wenn Sie eine Behauptung erhalten, ist etwas anderswo nicht in Ordnung.Sie verwenden das Wort "Initialisieren", sodass unklar ist, ob es sich um eine einmalige Zuweisung handelt oder ob sie mehrmals auftreten kann.
Wenn Sie nur eine einmalige Initialisierung benötigen, können Sie diese in den Konstruktor einfügen und den Konstruktor mit zwei Iteratorvektoren verwenden:
Verwenden Sie andernfalls zuweisen wie zuvor vorgeschlagen:
quelle
Sie können die Größe des Arrays automatisch "lernen":
Hoffentlich können Sie die Schnittstelle wie oben in set_data ändern. Es akzeptiert weiterhin ein Array im C-Stil als erstes Argument. Es nimmt es einfach als Referenz.
Wie es funktioniert
[Update: Sehen Sie hier für eine umfassendere Diskussion über die Größe Lernen]
Hier ist eine allgemeinere Lösung:
Dies funktioniert, weil das Array als Referenz auf ein Array übergeben wird. In C / C ++ können Sie ein Array nicht als Funktion übergeben, sondern es zerfällt in einen Zeiger und Sie verlieren die Größe. In C ++ können Sie jedoch einen Verweis auf das Array übergeben.
Um ein Array als Referenz zu übergeben, müssen die Typen genau übereinstimmen. Die Größe eines Arrays ist Teil seines Typs. Dies bedeutet, dass wir den Vorlagenparameter N verwenden können, um die Größe für uns zu lernen.
Es könnte noch einfacher sein, diese Funktion zu haben, die einen Vektor zurückgibt. Bei entsprechenden Compiler-Optimierungen sollte dies schneller sein, als es aussieht.
quelle
return { begin(source_array), end(source_array) };
ist auch möglichNun, Pavel war nah dran, aber es gibt noch eine einfachere und elegantere Lösung, um einen sequentiellen Container aus einem Array im AC-Stil zu initialisieren.
In deinem Fall:
quelle
array
Array haben (was normalerweise bedeutet, dass Sie von einem globalen oder lokalen (in der aktuellen Funktion deklarierten) Array kopieren). Im Fall des OP empfängt er einen Zeiger und eine Länge. Da die Länge nicht angegeben ist, können sie nicht zum Erhalt eines Zeigers auf ein Array mit Größe oder etwas anderem wechseln undstd::end
funktionieren daher nicht.vector
überlastet nichtoperator()
, daher wird dies nicht kompiliert.std::end
Das Aufrufen eines Zeigers ist ebenfalls sinnlos (in der Frage wird gefragt, ob ein Vektor aus einem Zeiger und einer separaten Längenvariablen zugewiesen werden soll). Es würde Ihre Antwort verbessern, mehr Kontext über das zu zeigen, was Sie vorschlagen möchtenDie schnelle generische Antwort:
oder fragenspezifisch:
basierend auf oben : Vergessen Sie nicht, dass Sie Zeiger als Iteratoren behandeln können
quelle
std::vector<double>::assign
ist der richtige Weg, weil es wenig Code ist . Aber wie funktioniert das eigentlich? Wird die Größe nicht geändert und dann kopiert? In der MS-Implementierung von STL verwende ich es genau so.Ich fürchte, es gibt keinen schnelleren Weg , um Ihre (Neu-) Initialisierung zu implementieren
std::vector
.quelle