通过值或const引用?

时间:2013-09-06 13:29:09

标签: c++ parameter-passing

a set of good rules to determine whether pass by value or const reference

  • 如果函数打算将参数更改为副作用,请执行 它由非const引用。
  • 如果函数没有修改其参数且参数是 原始类型,按价值看待。
  • 否则通过const引用获取它,除了以下内容 case:如果函数需要复制const 无论如何,请参考它。

对于构造函数如下,如何确定它?

class A
{
public:
    A(string str) : mStr(str) {} // here which is better, 
                                 // pass by value or const reference?

    void setString(string str)  { mStr = str; } // how about here?

private:
    string mStr;
};

4 个答案:

答案 0 :(得分:4)

在这种特殊情况下,假设C ++ 11并移动字符串的构造/赋值,你应该按值获取参数,然后移动到构造函数的成员。

A::A(string str) : mStr(std::move(str)) {}

setter的情况有点棘手,我不确定你是否真的想要/需要优化它的每一位...如果你想要最优化你可以提供两个重载,一个采用右值参考另一个采用const左值参考。无论如何,const lvalue reference可能是一个很好的方法:

void A::setString(string const& str) { mStr = str; }

为什么会有区别?

对于构造函数,该成员尚未构建,因此需要分配内存。您可以将该内存分配(以及数据的实际复制,但这是leaser cost)移动到接口,这样,如果调用者有临时值,则可以在没有额外内存分配的情况下转发它。

在分配的情况下,事情有点复杂。如果字符串的当前大小足以容纳新值,则不需要分配,但如果字符串不够大,则需要重新分配。如果将分配移动到接口(按值参数),则即使不需要,也将执行始终。如果分配是在函数内部(const引用参数)完成的,那么对于一小组情况(那些参数是临时的,大于当前缓冲区的情况),可以完成原本可以避免的分配。

答案 1 :(得分:3)

您网站上的文章不是是软件的一个很好的参考 工程。 (鉴于它,它也可能过时了 谈论移动语义,并且可以追溯到2003年。)

一般规则很简单:通过const引用传递类类型, 和其他类型的价值。有明确的例外:in 保持标准库的惯例,它也是 通常按值传递迭代器和函数对象。

其他任何事情都是优化,不应该进行 探查员说你必须这样做。

答案 2 :(得分:0)

在这种情况下,最好通过const引用传递参数。原因:字符串是类类型,您不需要修改它,它可以是任意大的。

答案 3 :(得分:0)

最好使用成员初始化列表初始化您的值,因为它提供了以下优点:

1)赋值版本创建一个默认构造函数来初始化mStr,然后在默认构造的值之上分配一个新值。使用MIL避免了这种浪费的构造,因为列表中的参数被用作构造函数参数。

2)这是初始化常量变量的唯一地方,除非这些只是可以在类中使用枚举的整数。枚举T {v = 2};

3)这是初始化参考文献的地方。

这就是我的建议:

#include <iostream>
#include <string>

class A
{
   private:
      std::string mStr;

   public:
      A(std::string str):mStr(str){}

      //if you are using an older version of C++11, then use 
      //std::string &str instead
      inline const void setString(std::string str)
      {
         mStr = str;
      }

      const std::string getString() const
      {
         return mStr;
      }
};

int main()
{
   A a("this is a 1st test.");

   a.setString("this is a 2nd test.");

   std::cout<<a.getString()<<std::endl;
}

看看这个: http://www.cplusplus.com/forum/articles/17820/