2017-09-27 66 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