2017-09-27 67 views
3

期間避免拷貝構造函數我有一個類A填充成員矢量

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

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

還有一些 「容器」 類B

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

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

和代碼:

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

我的問題是,如何優化B::addObject(A a)以避免任何複製。我想要的是通過B的方法將A類型的新對象添加到B.objects

+0

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

回答

5

有很多回答這個問題。你可以只改變你的B功能move(),並move()成函數:

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

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

您可以添加充分利用以const左值引用和右值引用的addObject重載

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 

你可以添加一個功能模板addObject表示:

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

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

無論哪種方式,有一個完全沒有必要複製到此處:

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

你想:

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

謝謝:)有一個問題:是否在你的身邊注意到了'text(std :: move(text))',在所有情況下都完全安全?另外,編譯器是否會自動執行任何操作(因爲優化而移動而不是複製)? – PolGraphic

+1

@PolGraphic是的 - 構造函數擁有'文本',所以它是安全的。不,不會。 – Barry

+0

感謝您的進一步解釋。這有點圍繞這個話題,但是'A a(2,5,「test」); b.addObject(std :: move(a));'在第二個解決方案中與'b有所不同。addObject(A {2,5,「test」});'在表現的情況下(第二個創建'A'而不是真的移動它)? – PolGraphic

1

您可以更改addObject的參數類型並使用emplace_back,以避免構造A的對象,此對象稍後將不會使用並將其複製到vector中。例如

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

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

這是一個很好的例子,但對我來說有一個小問題。現在我不會在'B'頭文件中的任何地方涉及'A'構造函數參數。在你的解決方案中,需要在'B'頭文件中提供更多的信息(我認爲它比'B'更接近'A')。這更多的是外觀的問題。 – PolGraphic

+0

@PolGraphic我沒有明白你的意思,你的意思是在'B.h'中加入'#include「A.h」'?不,它應該和'push_back'一樣,如果成員函數是在'B.cpp'中定義的,則不需要。 – songyuanyao

+0

不,我的意思是'B.h'內部,我將不得不知道並記住有關'A'構造函數參數的順序。如果有變化,我還需要修改'B.h'。 – PolGraphic