C ++ Reference vs Pointer最佳实践

时间:2014-04-28 21:38:00

标签: c++ pointers reference

我已经阅读了很多有关此问题的stackoverflow答案,我对答案不太满意,所以我想在这里收集它们。

当使用非基元和复杂对象调用函数时,通常建议通过引用传递它们,除非参数可能为NULL。这主要是因为引用保证具有值,因此您不必检查参数引用是否为NULL。

当函数的返回值是非基本和复杂的对象时,通常应该返回一个指针,因为很容易混淆一个返回引用的函数和一个返回值的函数,因为它们在调用时看起来是相同的。 / p>

以此类为例

struct Rectangle
{
    int x, y;
    int width, height;

    Rectangle(int x_, int y_, int width_, int height_)
        : x(x_)
        , y(y_)
        , width(width_)
        , height(height_)
    {
    }
};

class Image
{
public: 
    Image()
        : dimensions(0, 0, 0, 0)
    {}
    ~Image();

    void SetDimensions (const Rectangle& newDimensions) // Pass by reference is recommended practice
    {
        dimensions = newDimensions;
    }

    Rectangle GetDimensions()       // Returning by value is usually the best practice in this case
    {
        return dimensions;
    }
private:
    Rectangle dimensions;
};

这些是函数参数和返回类型中引用与指针的最佳实践吗?如果没有,请解释原因。

编辑1:更改了GetDimensions()以返回值,因为它被认为是有效的

3 个答案:

答案 0 :(得分:7)

引用是引用,值是值。它们具有不同的语义,只考虑保存复制操作的性能可能会成为一个严重的问题。

更具体地说,在理论上,只有当接收者关心对象的身份(而不仅仅是关于值)时才应该使用引用。如果标识不重要且被调用的函数/方法仅关注值,则应使用值。

如果您完全确定自己不会遇到别名生存期问题,那么您可能会决定传递一个const引用保存复制操作的值。

this answer中有一个详细的例子(顺便提一下,也是在讨论矩形),你可能会遇到一些非常微妙的错误。应该使用值代替。还要注意,在处理别名和生命周期问题时,const-correctness不会有任何帮助。

答案 1 :(得分:5)

关于处理对象访问和表示的最佳做法是使用此顺序:

  1. 使用普通对象和引用,除非你真的不能。
  2. 去除智能指针,除非你真的不能。
  3. 使用普通指针,如果你到目前为止,你应该真的知道你在做什么。
  4. 这适用于代码和类成员中对象的定义,以及将它们传递给函数和从函数传递它们。基本上无处不在。

    并且“真的不能”我的意思是写一个可编译的代码是不可能的。我不认为在编译器的当前状态,标准及其优化功能中更改此顺序是否有任何实际开销。

    一点解释。

    在人们遇到返回变量的麻烦之前,现在我们得到了RVO和NRVO。此外,c ++ 11还提供了std::function,lambdas和move语义。 IMO所有这一切都是为了能够使用对象和引用而不会产生任何开销,这就是为了使代码更易于维护,可读性和结构化。

    有时您需要使用指针,例如在抽象类接口的情况下。智能指针有助于对象管理,在这种情况下应该是默认的选择。例如,它们处理对象的删除,因此您可以安全地使用它们与标准容器,而无需额外的努力。 “双重免费”它们也更难,或更容易发现错误。

    然而,我看到SO上的一个人在某些游戏引擎上实现了他们的智能指针。他们不能使用标准库的祝福,而不得不自己做。这是你使用普通指针的时候。

答案 2 :(得分:1)

我会将SetDimensionsGetDimensions调整为:

// immutable access:
const Rectangle & GetDimensions() const;

// mutable access:
Rectangle & GetDimensions();

// or instead of the mutable GetDimensions():
void SetDimensions(const Rectangle & newDimensions);