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,几乎可以在不重载的情况下实现