指针,参考或智能指针?

时间:2014-11-26 09:58:58

标签: c++ pointers reference return

我有以下问题:

假设我有一个包含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?

2 个答案:

答案 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相关的所有内容,那会更好。