打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
05、C++ 11 函数参数类型传递分析与总结

C++自古以来, 针对函数参数类型的传递一直都有一些约定俗成的规定, 比如:
针对原始数据类型,直接使用传值形式传参

void test(int number);void test(bool enable);void test(double percent);

而针对结构体以及类, 通常都是:

  • 如果无需改变参数的值, 使用常量引用或者常量指针

  • 如果需要改变参数的值, 使用引用或指针

  • 如果需要拷贝参数的值,使用常量引用

示例代码

struct A {/// ...};class B {public:	/// ...private:	/// ...};void test_without_changed(const A& a);void test_without_changed(const B* b);void make_changed(A* a);void make_changed(B& b);A copy(const A& a);B copy(const B& b);

但是, 自动C++11之后这些或许就有一些变化了
在C++11开始, 引入了一个新的类型: 右值引用
何为右值引用? 说通俗点就是出现在等号右边的值的一个引用
右值引用相对的肯定会有左值引用,即 可以出现在等号左边的值的引用
这俩家伙具体有啥区别呢? 这里我就不多讲了, 自个儿查取咯

有了这个右值引用啊, C++11开始引入了一种新的拷贝: 移动拷贝
什么是 移动拷贝呢?

移动拷贝就是在拷贝出一个新的对象时, 将旧对象的值(内部资源)直接移动到新对象,旧对象直接变为一个(资源全部转移走了的)空对象

这又什么好处呢?

你看啊, 假设我有一个对象, 管理着一块相当大的内存,比如1G, 由于某种原因, 这个对象生命周期即将结束了, 但是该对象所管理的内存我还不想那么早释放掉, 我可以先使用移动构造将管理的内存块转移出去, 然后在其他地方继续使用新的对象来管理这块内存, 多好啊, 避免了资源释放再重新申请的开销

那再有了移动构造以后, 我们应该使用什么形式的传参更好呢?

  • 不需要拷贝

    • 不需要修改参数的值 —— 使用常量引用或者常量指针

    • 需要修改参数的值 —— 使用非常量引用或者指针

  • 需要拷贝 —— 使用传值
    示例代码

struct Some {	/// ...};/// 不拷贝,也不需要修改参数的值void test_without_copy_and_change(const Some& some);void test_without_copy_and_change(const Some* some);/// 不拷贝, 但是需要修改参数的值void change(Some& some);void change(Some* some);/// 拷贝Some copy_and_change_some_options(Some some); /// why ?

为什么需要拷贝的时候 只需要用一中形式的传参呢?

仔细想一想, 我们在参数传值的时候会发生什么 ? 当然会自动拷贝
对呀, 参数传值, 自动拷贝呀, 多简单

那为啥不写成下面这种呢?

Some copy_and_change_some_options(const Some& some);

在C++11之前,确实这样就可以了, 但是到了C++11之后, 上面的拷贝是不是还遗漏了什么呢?

除了 复制拷贝, 当然还得有个移动拷贝

那就是下面这样咯:

Some copy_and_change_some_options(const Some& some);Some copy_and_change_some_options(Some&& some);

这多麻烦啊, 每多一种, 旧都要写两种, 像我这么懒的人, 怎么可能会每次都写这么多???

当然是直接写成一种啊

Some copy_and_change_some_options(Some some); 

为啥这一种就能处理上面两种呢?

我们首先看复制构造

但我们直接传递一个对象做参数的时候, 是不是结果就跟复制拷贝一样了, 同样都是一次复制构造的开销

Some copy_and_change_some_options(const Some& some){	/// 一次copy	/// ... }Some copy_and_change_some_options(Some some) /// 直接在传值的时候一次copy{	/// ...}

然后再看移动构造

传值的时候, 的确都会调用一次构造函数, 但是并不是说, 传值只会调用复制构造呀

我们传值的时候, 把参数改成右值引用形式看看

Some copy_and_change_some_options(Some&& some){	/// 一次move	/// ...}Some copy_and_change_some_options(Some some) /// 传参时使用std::move(...)  一次move{	/// ...}

果然开销一样

总结

当不需要拷贝对象的时候, 我们使用引用或指针形式的参数, 如果不需要修改参数对象的值, 我们再加上const 修饰, 防止意外修改当需要拷贝参数对象的时候, 我们直接使用传值形式的参数, 这样既可以使用复制拷贝, 又可以使用移动拷贝, 很方便的合并了常量引用参数和右值引用参数
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
拷贝构造函数的参数类型必须是引用(转)
引用参数与引用返回值,临时对象
C++拷贝构造函数详解(转)
【博文连载】C 中的“引用”
C++的几个重要问题
C++ 学习要点
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服