我有以下问题:
假设我有一个包含100个对象的Vector,因此创建副本会很糟糕。
class MyClass
{
private:
vector<MyObject> mVector;
};
//return by reference
vector<object>& MyClass::GetVector1()
{
return mVector;
}
vector<object>* MyClass::GetVector2()
{
return &mVector;
};
按引用返回很快并且不会生成副本。 矢量应该仍然可以在MyClass中使用,因此我不想移动它。 但是使用这个GetVector()方法的最佳方法是什么?:
class MyOtherClass
{
private:
vector<MyObject>* myVector;
vector<MyObject>& myVector2;
vector<MyObject> myVector3;
MyClass m;
};
myVector2 = m.GetVector1(); //only works in an initializer list!
但是如果在创建对象时无法初始化向量怎么办? 假设我有一个OnInit()方法,它将在需要时调用:
void MyOtherClass::OnInit()
{
myVector = m.GetVector2(); //no copy using return by reference
myVector = &m.GetVector1(); //no copy returning a pointer
myVector3 = m.GetVector1(); //copy
}
很多人告诉我使用像myVector这样的指针是非常糟糕的,但为什么????? 我应该使用smart_pointers吗? (请举个例子,如何使用上面给出的代码)
或者有更好的方法来获得快速的表现吗?
编辑:
答案检查我选择的答案如下。
另外我想添加移动语义。
但这在很大程度上取决于代码的用途,有时你真的想要复制,你将无法避免它。如果你知道对象比跟踪它的代码持续的时间更长,只要你想要应用更改,指针就可以了,否则使用const ref。
如果你不再需要你返回的对象并且它可能会被销毁,你可以使用return by value,这是好的,因为编译器可能会通过移动来优化它,但你可以明确地使用movesemantics并移动向量外的向量,因为向量元素是动态分配的,容器是可移动的。点击此链接:Is returning by rvalue reference more efficient?
答案 0 :(得分:3)
此时只有一个公共对象。您不需要 getter :
struct X {
std::vector<Y> vec;
X(..) : vec(..) { .. }
};
然后你可以简单地用它:
X x(..);
x.vec.some_member_function();
auto& z = x.vec;
z.vec.some_member_function();
如果你真的需要使用成员函数版本,那么使用return by reference,这有点像惯用语,即使它与指针性能返回基本相同:
vector<Y>& X::GetVector() {
return mVector;
}
然后将其用作:
X x(..);
x.GetVector().some_member_function();
auto& z = x.GetVector();
z.some_member_function();
智能指针解决了处理资源和描述所有权的问题。在这种情况下,鉴于std::vector
已经拥有并在内部处理自己的资源,它们没有多大意义。
答案 1 :(得分:0)
如果初始化列表可以初始化myVector
,那就去做吧!否则你必须使用指针。
指针不错,它们的限制性比引用要少。如果myVector
接受nullptr / 0值,则可以使用指针。当您使用引用时,它会告诉您它不会为空(或者至少不应该为空),并且您不需要在要使用它时检查myVector == 0
是否为空。
我应用相同的约定来返回值。比如像我这样的宣言
vector<object>* MyClass::GetVector2()
表示函数可以返回nullptr / 0,而
vector<object> & MyClass::GetVector2()
不能。
要安全地使用指针或引用,您必须确保MyClass
对象比MyOtherClass
对象更长。在您的示例中,它是满意的,因为MyClass
对象是MyOtherClass
的成员。
现在关于你的设计。如果您可以通过MyClass::mVector
功能访问GetVector()
,为什么要初始化参考?此外,你真的需要这样的访问?如果MyClass
维护与mVector
相关的所有内容,那会更好。