首页
学习
活动
专区
圈层
工具
发布

【C++】--函数参数传递:传值与传引用的深度解析

本篇博客将详细解析这两种传递方式的工作原理、优缺点及适用场景。 一.传值传参 传值传参是最直观的参数传递方式,当函数被调用时,实参的值会被复制一份,然后传递给形参。...二.传引用传参 传引用传参是将实参的引用(别名)传递给函数,函数内部对形参的操作实际上是直接操作实参本身。这种方式不会产生数据拷贝,效率更高。...优先使用传值的场景: 传递基本数据类型(int、float、char 等) 传递小型结构体或类(拷贝成本低) 不希望函数修改实参的值 函数需要保留参数的原始值用于内部操作 // 传值适合小型数据 int...函数需要返回多个结果(通过修改引用参数) // 传引用适合大型对象和需要修改实参的场景 void splitString(const string& input, string& first, string...明确你的意图:如果函数需要修改参数,使用引用;如果不需要,考虑 const 引用或传值 注意默认参数与引用:引用参数不能有默认值,这是 C++ 的语法规定 传值和传引用是 C++ 中两种基本的参数传递方式

26310

【C++】This指针和复制构造函数

CTime(CTime& time);//使用类名对象作为参数,传引用 调用复制构造函数的时机: 在什么情况下使用复制构造函数 1.以其他对象作为参数创建新对象时。...比如:创建一个新的对象的时候,把原来的一个对象作为参数传递给新的对象作为构造函数 CTime time; CTime time2(time);//会自动执行复制构造函数,复制成员等 CTime::...2.类对象(传值)作为函数参数时。...如果我们把复制构造函数 CTime::CTime(CTime& time)修改为CTime::CTime(CTime time) CTime& time是一个引用类型的参数,现在将引用去掉的话,就满足了调用复制构造函数中的一种...被调函数对形参的任何操作都被处理成间接寻址,即通过栈中存放的地址访问主调函数中的实参变量。正因为如此,被调函数对形参做的任何操作都影响了主调函数中的实参变量。

1.4K20
  • 您找到你想要的搜索结果了吗?
    是的
    没有找到

    如何禁止函数的传值调用

    对于基本数据类型的变量作为实参进行参数传递时,采用传值调用与引用调用和指针调用的效率相差不大。但是,对于类类型来说,传值调用和引用调用之间的区别很大,类对象的尺寸越大,这种差别越大。...传值调用与后面两者的区别在于传值调用在进入函数体之前,会在栈上建立一个实参的副本,而引用和指针滴啊用没有这个动作。建立副本的操作是利用拷贝构造函数进行的。...为使程序通过编译,需将show()函数的定义改为如下形式: void show(const A& a){ cout<<a.num<<endl; } 3.拷贝构造函数的说明 (1)如果将拷贝构造函数中的引用符号去掉...&,编译将无法通过,出错的信息如下:非法的复制构造函数: 第一个参数不应是“A”。...原因是如果拷贝构造函数中的参数不是一个引用,即形如A(const A a),那么就相当于采用了传值的方式(pass-by-value),而传值的方式会调用该类的拷贝构造函数,从而造成无穷递归地调用拷贝构造函数

    4.1K10

    C++如何禁止函数的传值调用

    传值调用与后面两者的区别在于传值调用在进入函数体之前,会在栈上建立一个实参的副本,而引用和指针调用没有这个动作。建立副本的操作是利用拷贝构造函数进行的。...为使程序通过编译,需将show()函数的定义改为如下形式: void show(const A& a) { cout<<a.num<<endl; } 3.拷贝构造函数的说明 (1)如果将拷贝构造函数中的引用符号去掉...&,编译将无法通过,出错的信息如下:非法的复制构造函数: 第一个参数不应是“A”。...原因是如果拷贝构造函数中的参数不是一个引用,即形如A(const A a),那么就相当于采用了传值的方式(pass-by-value),而传值的方式会调用该类的拷贝构造函数,从而造成无穷递归地调用拷贝构造函数...作为实参以值传递的方式传递给一个函数; c. 在函数体内返回一个对象时,也会调用返回值类型的拷贝构造函数; d. 需要产生一个临时类对象时(类对象作为函数返回值会创建临时对象)。

    3.6K30

    C++抛出异常与传递参数的区别

    相同点就是传递参数和传递异常都可以是传值、传引用或传指针。 (1)区别一:C++标准要求被作为异常抛出的对象必须被拷贝复制。考察如下程序。...(2)区别二:因为异常对象被抛出时需要拷贝,所以抛出异常运行速度一般会比参数传递要慢。当异常对象被拷贝时,拷贝操作是由对象的拷贝构造函数完成的。...这是因为localStuff通过拷贝构造函数传递给异常对象,而异常对象又通过拷贝构造函数传递给catch子句中的对象w。...并且调用的拷贝构造函数是属于被抛出对象的静态类型。当通过传值方式捕获时,对象被拷贝了两次。...对象作为引用参数传递给函数时,不需要进行额外的拷贝; 第二,对象作为异常被抛出与作为参数传递给函数相比,前者允许的类型转换比后者要少(前者只有两种类型转换形式); 第三,catch子句进行异常类型匹配的顺序是它们在源代码中出现的顺序

    2.2K20

    在Spring Boot启动时运行定制的代码

    1.执行bean初始化的方法 Spring启动应用程序后运行某些逻辑的最简单方法是将代码作为所选bean引导过程的一部分来执行。...理论上,您可以使用构造函数而不是单独的方法,但将对象的构造与其实际责任分开是一种很好的做法。...这就是你可以挂钩Spring Boot初始化过程的重点。 首先更改main方法中的代码,以将启动挂钩附加到单独的方法中。您应该在应用程序启动之前添加Spring Boot挂钩。...getProperty("java.runtime.version"); log.info("Running with Java {}", version); }); } 根据事件类型,Spring传递给侦听器的对象可以让您访问几个有用的操作...如果是这种情况,那么前一段中的解决方案将无法发挥作用。除非有增加额外步骤。 如果将应用程序部署为常规WAR文件,则可能已经拥有SpringBootServlerInitializator的自定义实现。

    2.9K20

    C++抛出异常与传递参数的区别

    相同点就是传递参数和传递异常都可以是传值、传引用或传指针。 下面考察二者的不同点。 (1)区别一:C++标准要求被作为异常抛出的对象必须被拷贝复制。 考察如下程序。...(2)区别二:因为异常对象被抛出时需要拷贝,所以抛出异常运行速度一般会比参数传递要慢。 当异常对象被拷贝时,拷贝操作是由对象的拷贝构造函数完成的。...这是因为localStuff通过拷贝构造函数传递给异常对象,而异常对象又通过拷贝构造函数传递给catch字句中的对象w。...并且调用的拷贝构造函数是属于被抛出对象的静态类型。当通过传值方式捕获时,对象被拷贝了两次。...对象作为引用参数传递给函数时,不需要进行额外的拷贝; 第二,对象作为异常被抛出与作为参数传递给函数相比,前者允许的类型转换比后者要少(前者只有两种类型转换形式); 第三,catch子句进行异常类型匹配的顺序是它们在源代码中出现的顺序

    2.4K30

    C++笔记-C++11(二)

    这是我们对之前写的list所进行的修改,这里注意我们在参数部分虽然用了右值引用,但是上节我们讲了变量表达式均为左值,所以我们在复用传参时还要注意将变量表达式通过move函数强转为右值,不然还是会调用左值的拷贝构造函数...这是没有问题的list,和我们调用库中的一样,但是: 这里我就把ListNode中的构造函数少写了move函数来将参数强转为右值,通过上图可以看出结果发生了改变,只调用了左值的拷贝构造函数,所以我们在自己联系时一定要注意这点...下面我们就来解决这个问题: 首先 C++中不能直接定义引⽤的引⽤如 int& && r = i; ,这样写会直接报错,通过模板或 typedef 中的类型操作可以构成引⽤的引...这里就要引入完美转变forward函数: 完美转发forward本质是⼀个函数模板,它主要还是通过引⽤折叠的⽅式实现,上⾯⽰例中传递给 Function的实参是右值,T被推导为int,没有折叠...我们通过在模式的右边放⼀个省略号(...)来触发扩展操作。

    12310

    C++11之可变参数模板

    Print 函数接收一个参数包 args,然后通过 ShowList(args...) 的方式将参数包展开,并将展开后的结果传递给 ShowList 函数。...参数包的展开 参数包展开是指将参数包中的每个参数依次展开,以便在代码中对每个参数进行操作。展开操作是通过 ... 运算符来完成的。 在 Print 函数中,ShowList(args...)...它接收一个参数包 args,然后通过 GetArg(args)... 的方式将参数包展开,并将展开后的结果作为参数传递给 Arguments 函数。...参数包的展开 参数包展开是指将参数包中的每个参数依次展开,以便在代码中对每个参数进行操作。展开操作是通过 ... 运算符来完成的。 在 Print 函数中,GetArg(args)......运算符的作用是将 GetArg(args) 对每个参数的调用结果展开成一个参数列表,然后将这个参数列表传递给 Arguments 函数。

    9610

    【Java】方法参数传递机制分析:传值与传引用

    本文将详细分析 Java 中的 传值调用 和 传引用调用,以及如何通过对象引用模拟传址调用的效果,并澄清一些常见的误解和疑问。...Java Java 中的传值机制 基本数据类型的传值 Java 的参数传递机制基于 传值,即方法接收参数时,会将实际传递给它的值复制给形参。这意味着,形参的变化不会影响到原始实参。...System.out.println("After: " + person.name); // 输出 Alice } } 分析: Person 类中定义了一个 name 属性,并通过构造函数初始化...传值调用 传值调用(Call by Value)意味着将实际参数的副本传递给方法。对于基本数据类型的参数,方法内部对副本的修改不会影响到实际参数的值。这是 Java 中处理基本数据类型的方式。...小结 本文深入分析了 Java 中的参数传递机制,特别是 传值调用 和 传引用调用 的不同,以及如何通过对象引用模拟传址调用的效果。

    1.6K10

    React组件通讯

    大白话:一个组件使用另一个组件的状态 props 组件是封闭的,要接收外部数据应该通过props来实现 props的作用:接收传递给组件的数据 传递数据:给组件标签添加属性 接收数据:函数组件通过参数props...推荐将props传递给父类构造函数 super(props) } render() { return 接收到的数据:{this.props.age} } } 组件通讯三种方式 父传子 子传父 非父子 父传子 父组件提供要传递的state数据 给子组件标签添加属性,值为 state 中的数据 子组件中通过 props 接收父组件中传递的数据...父组件提供一个回调函数(用于接收数据) 将该函数作为属性的值,传递给子组件 子组件通过 props 调用回调函数 将子组件的数据作为参数传递给回调函数 父组件提供函数并且传递给字符串 class Parent...兄弟 将共享状态提升到最近的公共父组件中,由公共父组件管理这个状态 思想:状态提升 公共父组件职责: 提供共享状态 提供操作共享状态的方法 要通讯的子组件只需通过 props 接收状态或操作状态的方法

    4.4K20

    八、python学习笔记-面向对象-类对象

    (对象)访问 2、静态方法:保存在类中,由类直接调用,self不在是必须的,通过@staticmethod 声明,但是可以传递参数,类似于直接写了一个函数 3、类方法:保存在类中,由类直接调用...('method') # 通过实例调用,创建类的实例foo,创建时会执行构造方法,打印init,然后调用bar方法打印methodo foo1 = Foo1() foo1.bar() #...会自动将实例(foo)传递给self # 通过类调用,并未执行构造方法,说明没有创建实例,直接调用bar打印hello # 通过类调用需要传参,因为定义方法时设置了形参self,没有创建实例需要自己传入..., a2) # 通过类调用,不需要传参 Foo2.bar() # 通过类调用,传递参数 Foo2.bar2(1, 2) # 示例3、类方法 class Foo3: @classmethod...def bar(cls): # 类方法使用cls而非self,必填.cls代指类,所以不需要实例 print('classmethod') Foo3.bar() # 会自动将类传递给形参

    97431

    Flutter中的基本路由、命名路由、替换路由,返回到根路由

    //命名路由跳转传值 Navigator.pushNamed(context, "/search", arguments: {"info":"777"}); 现在我们已经了解了命名路由传值该怎么去操作了...其实,我们还可以对main.dart中的代码进一步进行优化,也就是说,我们还可以将 Tabs 这个主页面也通过命名路由进行管理,代码如下: //Routes.dart //配置命名路由信息 final...() => _DetailPageState(arguments: arguments);//3,将参数值传递给_DetailPageState } class _DetailPageState extends...State { Map arguments;//4,定义传值参数 _DetailPageState({this.arguments});//5,重新写构造函数 @override..._TabsState(this.currentIndex);//3,将参数值传递给_TabsState } class _TabsState extends State { int _

    10.1K21

    C++现代模板编程核心技术精解:从类型分类、引用折叠、完美转发的内在原理,到可变模板参数的基本语法、包扩展机制及emplace接口的底层实现

    列表初始化统一了对象的初始化方式,支持内置类型和自定义类型,通过std::initializer_list实现容器初始化。右值引用区分左值和右值,通过移动语义提高效率,解决了传值返回的拷贝问题。...我们通过模板或者typedef中的类型操作可以构成引用的引用时,这时C++11给出了一个引用折叠的规则:右值引用的右值引用折叠成右值引用,所有其他组合均折叠成左值引用。...也就是说—— ok,我们通过下面的程序可以很好的展示模板和typedef 时构造引用的引用时的引用折叠规则,我们来一个一个的仔细理解一下—— 这里为了更好的看出区别,我们就进行显示模板参数—— template...我们通过在模式的右边放一个省略号(…)来触发扩展操作。底层的实现细节如下图所示。 C++还支持更复杂的包扩展,直接将参数包依次展开依次作为实参给一个函数去处理。...好像没有什么差别 但是emplace_back可以直接把构造pair参数包传下去,直接用pair参数包构造pair,这个效果push_back是做不到的 emplace_back可以传构造pair的参数包

    16310

    对 UAF 漏洞 CVE-2015-2546 的分析和利用

    如果用户进程先前通过利用技巧构造了特殊关联和属性的菜单窗口对象,并设置特定的挂钩处理程序,那么在调用 xxxSendMessage 向目标菜单窗口对象发送 MN_SELECTITEM 消息期间,执行流返回到用户上下文...当返回值是真实的菜单窗口对象地址时,函数将该窗口对象作为目标窗口对象,将鼠标坐标位于的菜单项序号作为参数 wParam 向目标窗口对象发送 0x1E5(MN_SELECTITEM) 消息以执行选择菜单项的操作...设置这种类型的挂钩会在每次线程将消息发送给窗口对象之前调用。...因此,我们可以通过设置这种类型的挂钩处理程序,并在处理程序函数中对目标菜单窗口对象调用 DestroyWindow 等函数以触发对目标窗口对象的销毁操作。...后续的实际内核利用的操作将通过这里的 ShellCode 代码在内核上下文中进行。

    1.8K10
    领券