Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/125.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 传递值还是常量引用?_C++_Parameter Passing - Fatal编程技术网

C++ 传递值还是常量引用?

C++ 传递值还是常量引用?,c++,parameter-passing,C++,Parameter Passing,有 如果函数打算将参数更改为副作用,请执行以下操作 它是通过非常量引用实现的 如果函数不修改其参数且参数为 基元类型,按值取值 否则,通过常量引用获取,以下情况除外 案例:如果函数需要复制常量 不管怎么说,还是参考它的值 对于以下构造函数,如何确定它 class A { public: A(string str) : mStr(str) {} // here which is better, // pass by v

  • 如果函数打算将参数更改为副作用,请执行以下操作 它是通过非常量引用实现的
  • 如果函数不修改其参数且参数为 基元类型,按值取值
  • 否则,通过常量引用获取,以下情况除外 案例:如果函数需要复制常量 不管怎么说,还是参考它的值
对于以下构造函数,如何确定它

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;
};

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

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

A::A(string str) : mStr(std::move(str)) {}
二传的情况有点棘手,我不确定你是否真的想/需要优化它的每一点。。。如果您想最大限度地优化,可以提供两个重载,一个采用右值引用,另一个采用常量左值引用。无论如何,常量左值引用可能是一种足够好的方法:

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

为什么不同

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


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

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

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;
}
#包括
#包括
甲级
{
私人:
std::字符串mStr;
公众:
A(std::string str):mStr(str){}
//如果您使用的是旧版本的C++11,则使用
//std::string&str
inline const void setString(std::string str)
{
mStr=str;
}
常量std::string getString()常量
{
返回mStr;
}
};
int main()
{
A(“这是第一次测试”);
a、 设置字符串(“这是第二次测试”);
std::cout您站点上的文章不是软件的好参考
(考虑到
谈论移动语义,日期为2003年。)

一般规则很简单:通过常量引用传递类类型, 还有显式的例外:在 与标准库的约定保持一致,它也是 通常通过值传递迭代器和函数对象

其他任何事情都是优化,在
探查器说你必须这样做。

构造函数的平均性能比你使用
mStr(std::move(str))时要好
。如果你真的需要对其进行更多优化,你仍然可以使其过载。无论如何你都必须复制一份,不是吗?@chris我认为你的
移动
方式也适用于
设置字符串
。如果
字符串
没有移动和赋值,哪种方式更好?谢谢。是的,我没有太多地查看赋值运算符,但我支持摆出它的姿势。无论如何,我可能会说一个常量引用。我不同意;如果你正在复制(或移动)参数,并且@Angew,该链接似乎断了。我得到一个数据库错误。我不确定编译器是否能够避免双重复制。@patrickvacek哇!我当然希望这是暂时的;这是一篇优秀的文章。完整标题是“想要速度?按值传递。”这似乎是@Manu343726。通过按值获取参数并在创建“副本”时对其进行
std::move()
-ing,几乎可以在不重载的情况下实现