effective c++ 20 传引用代替传值

这篇具有很好参考价值的文章主要介绍了effective c++ 20 传引用代替传值。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

effective c++ 20 传引用代替传值

本节,作者开始讨论引用。我们知道c语言已经有了指针,通过指针我们也就可以修改变量本身,而不是修改变量的副本(传值), 那么在c++中又搞出来个引用, 那么其是不是有点重复?

分析

我们知道在函数的传参中,如果传递的是指针, 那么就不可避免的要进行取地址和解引用,如下面的这段代码所示,就需要使用"&“和”*"。这就可给我们的代码增加了一定的复杂性。其实c++引入引用也就是为了简化这种写法。

#include <iostream>

void print(int* a)
{
    *a = 4;
    std::cout << *a << std::endl;
}

int main()
{
    int a = 3;
    print(&a);
}

上面的代码修改成用引用的方式,是不是就简化了很多。

#include <iostream>

void print(int& a)
{
    a = 4;
    std::cout << a << std::endl;
}

int main()
{
    int a = 3;
    print(a);
}

因此我们在c++中,涉及传参的时候,要尽量使用引用。但是要强调的是,引用并不能取代指针,涉及内存的操作的时候,指针还是不可替代的。

由于引用有指针的特性,在传参的时候是没有copy的行为的。例如下面这个validateStudent函数,使用了常引用作为入参,避免了对象的拷贝。如果用传值的方式, 其内部有多个string对象要涉及拷贝,这将是低效的。

class Person
{
public:
	Person() : name("AAAA"), addr("BBBB")
	{
	}
	virtual ~Person() {}

private:
	std::string name;
	std::string addr;
};

class Student : public Person
{
public:
	Student() : schoolName("CCCC"), schoolAddr("DDDD")
	{
	}
	~Student() {}

private:
	std::string schoolName;
	std::string schoolAddr;
};

bool validateStudent(const Student& s);

另外, 由于引用的背后是由指针实现的,所以其将拥有"多态"的功能。 如下面中的printNameAndDisplay函数, 其入参是一个Window类的引用,在类的继承关系上,WindowWithScrollBars继承于Window。因此当传入的对象是Window对象时,w.display将调用window类的display方法,当传入的参数是WindowWithScrollBars类的对象时,w.display将调用WindowWithScrollBars类的display方法。

class Window
{
public:
	std::string name() const { return "WINDOW"; }
	virtual void display() const
	{
		std::cout << "Display: window" << std::endl;
	}
};

class WindowWithScrollBars : public Window
{
public:
	void display() const
	{
		std::cout << "Display: window with scroll bars" << std::endl;
	}
};

void printNameAndDisplay(const Window& w)
{
    std::cout << w.name();
    w.display();
}

上面主要讲解了传引用的好处, 那么什么时候我们引用考虑传值呢?

作者这里也给出了解答, 下面三种场景可以考虑直接传值:

  • 内置类型(只读不修改时)
  • STL迭代器
  • 函数对象

关于STL迭代器和函数对象为什么可以考虑传值,我在知乎上搜到了下面的解释,我觉得比较有道理:

很多时候迭代器可以做成可平凡复制的小对象(有时就是裸指针或裸指针直接外包),这时值传递迭代器和传递一个指针开销相同。不过例外也是存在的。

函数对象的话,无状态函数对象和函数指针是常见的情况。不过“大块头”的函数对象(如 std::function 或状态庞大的函数对象)也不能说少见。这时选择传值还是 const 引用可能就需要斟酌。文章来源地址https://www.toymoban.com/news/detail-454766.html

总结

  • 尽量以传常引用去替代传值。前者通常比较高效,并且可以避免切割问题。
  • 以上规则并不适用于内置类型 ,以及STL的迭代器和函数对象,对它们而言,传值往往比较合适。

到了这里,关于effective c++ 20 传引用代替传值的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 小程序组件引用、子父组件传值、监听等详细介绍、component、observers

    目录 组件生命周期  组件引用 组件传值 父组件给子组件传值  子组件给父组件传值 observers 数据监听  注意事项 在介绍组件属性时,先介绍下组件的生命周期,可用的全部生命周期如下表所示: 生命周期 参数 描述 最低版本 created 无 在组件实例刚刚被创建时执行 1.6.3 att

    2024年02月06日
    浏览(33)
  • Effective Java笔记(20)接口优于抽象类

            Java提供了两种机制,可以用来定义允许多个实现的类型:接口和抽象类。自从Java 8为继承引入了 缺省方法 ( default method),这两种机制都允许为某些实例方法提供实现。主要的区别在于,为了实现由抽象类定义的类型,类必须成为抽象类的一个子类。因为Java只允许

    2024年02月14日
    浏览(43)
  • uniapp:引用百度地图,创建地面图片叠加层及html页面向uniapp页面传值交互

    1.第一步,创建html页面,引用百度地图,创建地面图片叠加层 根据官方指示,创建html页面位置 在html页面里引用uni.webview.1.5.4文件 在html页面里创建地面图片叠加层: var map = new BMapGL.Map(\\\'container\\\');     map.centerAndZoom(new BMapGL.Point(105.753869, 34.571069), 18);     map.enableScrollWheelZoo

    2024年02月09日
    浏览(38)
  • C# 使用SIMD向量类型加速浮点数组求和运算(4):用引用代替指针, 摆脱unsafe关键字,兼谈Unsafe类的使用

    作者: zyl910 目录 一、引言 二、办法说明 2.1 历史 2.2 局部引用变量与引用所指的值(类似指针的 地址运算符 、间接运算符 * ) 2.3 重新分配局部引用变量(类似指针直接赋值) 2.4 引用地址调整(类似指针加减法) 2.5 引用地址比较(类似指针比较) 2.6 重新解释(类似C++的

    2024年02月15日
    浏览(42)
  • 【Effective C++】让自己习惯C++

    C++由四个次语言组成: C:过程形式,没有模板、没有异常、没有重载 Object-Oriented C++:面向对象形式,类(构造函数和析构函数)、封装、继承、多态 Template:泛型编程、模板元编程 STL:容器、算法、迭代器和函数对象 目标是让编译器来替代预处理器,使用预处理器会存在

    2024年01月21日
    浏览(50)
  • effective c++ 条款2

    尽量用const,enum,inline替换#define 总结就是: 双const:指针不能变(只能指向这一块内存空间),指向的内存单元的值也不能变。 或者可以使用string常量代替: 类的静态成员 在头文件声明,在cpp文件中定义 这样也就完成了常量的定义。 可以在其他函数中,直接调用常量GamePl

    2024年02月15日
    浏览(42)
  • Effective C++ 条款四

    使用未初始化的值会导致不明确的行为 对于内置的数据类型(char,int,float,double等),在使用前必须进行初始化。 对于class来说,在使用对象之前,必须使用构造函数对成员变量进行初始化 但是需要注意赋值和初始化的区别 构造函数中的赋值操作(非初始化) 例如下面的构造函数

    2024年02月05日
    浏览(40)
  • effective c++ 笔记

    TODO:还没看太懂的篇章 item25 item35 模板相关内容 可以将C++视为以下4种次语言的结合体: C 面向对象 模板 STL 每个次语言都有自己的规范,因此当从其中一个切换到另一个时,一些习惯或守则是可能会发生变化的。 用const替换#define有以下2个原因: #define定义的符号名称可能没

    2024年02月10日
    浏览(28)
  • C++笔记-effective stl

    熟悉stl本身 慎重选择stl容器,每一种stl容器对应不同的使用场景,比如deque往往比vector更加合适 封装stl容器,积极的使用stl,可以高效的使用它 积极使用其对应迭代器使用的函数,比如做相加运算使用accumulate替代for循环,可以更加高效 调用对应的函数的时候,不使用过于复

    2024年01月18日
    浏览(41)
  • 【Effective C++】4. 设计与声明

    如何创建和销毁 初始化对象和对象的赋值应该有什么差别 以值传递意味着什么 新type的合法值 继承体系 类型转换 操作符重载 继承标准 未声明接口 type一般化(template) 有以下几个优势: 1. 语法一致性:访问class成员时每一个都是函数,不需要记住是否需要小括号 2. 使成员

    2024年01月24日
    浏览(37)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包