8

有一套很好的规则来确定是按值传递还是 const 引用传递

  • 如果函数打算将参数更改为副作用,请通过非常量引用获取它。
  • 如果函数不修改其参数并且参数是原始类型,则按值获取。
  • 否则,通过 const 引用获取它,但以下情况除外: 如果该函数无论如何都需要制作 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

4 回答 4

4

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

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

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

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

为什么有区别?

在构造函数的情况下,成员尚未构建,因此需要分配内存。您可以将该内存分配(以及数据的实际复制,但这是租用者成本)移动到接口,以便如果调用者有一个临时的,它可以被转发而无需额外的内存分配。

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

于 2013-09-06T14:21:58.733 回答
3

您站点的文章不是软件工程的良好参考。(它也可能已经过时了,因为它谈到了移动语义并且可以追溯到 2003 年。)

一般规则很简单:通过 const 引用传递类类型,通过值传递其他类型。有明确的例外:按照标准库的约定,通常按值传递迭代器和函数对象。

其他任何事情都是优化,在分析器说你必须这样做之前不应该进行。

于 2013-09-06T15:31:47.237 回答
0

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

于 2013-09-06T13:32:34.850 回答
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/

于 2013-09-06T14:24:54.520 回答