2017-09-27 4 views
3

Ich habe eine Klasse A:Vermeiden Copykonstruktor während bevöl Mitglied Vektor

class A { 
    int value1; 
    int value2; 
    std::string text; 

public: 
    A(int value1, int value2, std::string text) 
    : value1(value1), value2(value2), text(text) { } 
}; 

und einige "Container" Klasse B:

class B { 
    std::vector<A> objects; 
    ... 

public: 
    ... 
    void addObject(A a) { 
    objects.push_back(a); 
    } 
}; 

Und Code:

B b; 
A a(2, 5, "test"); 
b.addObject(a); 
//I no longer need a from now on 

Mein Problem ist, wie man B::addObject(A a) optimiert, um jedes Kopieren zu vermeiden. Was ich erreichen will, ist ein neues Objekt vom Typ A zu B.objects über B Methode hinzufügen.

+0

bezogen werden: https://stackoverflow.com/questions/2139224/how-to-pass- objects-to-functions-in-c – NathanOliver

Antwort

5

Es gibt viele Antworten auf diese Frage. Sie könnten nur Ihre B Funktion move() ändern und move() in dieser Funktion:

void addObject(A a) { objects.push_back(std::move(a)); } 

b.addObject(std::move(a)); // two moves 

Sie Überlastungen von addObject hinzufügen könnte, die von const lvalue Bezug nehmen und durch rvalue Referenz

void addObject(A const& a) { objects.push_back(a); } 
void addObject(A&& a) { objects.push_back(std::move(a)); } 

b.addObject(std::move(a)); // one move 

Sie könnten ein hinzufügen Funktionsvorlage für addObject die emplaces:

template <class... Args> 
void addObject(Args&&... args) { objects.emplace_back(std::forward<Args>(args)...); } 

b.addObject(2, 5, "test"); // zero moves 

So oder so, ist es eine völlig unnötige Kopie hier:

A(int value1, int value2, std::string text) 
: value1(value1), value2(value2), text(text) { } 

Sie wollen:

A(int value1, int value2, std::string text) 
: value1(value1), value2(value2), text(std::move(text)) { } 
+0

Danke :) Eine Frage: ist der 'text (std :: move (text))' von deiner Seitennotiz in allen Fällen völlig sicher? Ist es nicht etwas, das der Compiler automatisch so oder so tun würde (verschieben statt dort kopieren wegen Optimierung)? – PolGraphic

+1

@PolGraphic Ja - der Konstruktor besitzt 'text', so dass es sicher ist, von dort fortzuschreiten. Und nein, wird es nicht. – Barry

+0

danke für die weitere Erklärung. Es ist ein bisschen um das Thema, aber 'A a (2,5," Test "); b.addObject (std :: move (a)); 'in der zweiten Lösung ist eine andere als' b.addObject (A {2,5, "test"}); 'im Falle der Leistung (die zweite erzeugt' A' und bewegt sie dann oder nicht wirklich)? – PolGraphic

1

Sie können den Parameter Typen addObject ändern und emplace_back, verwenden Sie ein Objekt von A zu vermeiden konstruieren, die später nicht verwendet und in die vector kopieren. z.B.

void addObject(int value1, int value2, std::string text) { 
    objects.emplace_back(value1, value2, text); 
} 

und

B b; 
b.addObject(2, 5, "test"); // construct the element directly into the vector without constructing A 
+0

Das ist ein guter, aber es gibt ein kleines Problem für mich. Momentan verweise ich nicht auf 'A'-Konstruktorparameter irgendwo in' B'-Header-Datei. Und mit Ihrer Lösung würde es notwendig sein, weitere Informationen (die ich glaube, dass sie mehr mit A als B verwandt sind) in der B-Header-Datei anzugeben. Es ist mehr die Frage des Aussehens. – PolGraphic

+0

@PolGraphic Ich habe nicht verstanden was du meinst, du meintest hinzufügen '#include" A.h "' in 'B.h'? Nein, es sollte dasselbe mit dem sein, der 'push_back' verwendet, wenn die Mitgliederfunktion in' B.cpp' definiert ist, wird es nicht benötigt. – songyuanyao

+0

Nein, ich meine, innerhalb von 'B.h' muss ich mich über' A' Konstruktorparameter-Reihenfolge informieren und erinnern. Und wenn ich damit etwas zu tun habe, muss ich auch 'B.h' modifizieren. – PolGraphic

Verwandte Themen