关于函数的传参问题

时间:2022-03-09 18:49:33
C++中引入了按 引用传参的机制,实际上就是对实参起了一个别名,达到直接控制实参的目的。与按 传参的方法相比,避免了开辟实参副本的时空开销。还可以可以通过const对是否允许改变实参进行控制。
我想问问各位大神,这样看来“按引用传参”是不是可以完全取代“按值传参”了呢?如果真的这样。按值传参的机制还有什么存在的意义呢?本人小菜,求指点!

49 个解决方案

#1


你完全用传引用代替值传递没什么问题,《Effective C++》中也是这样建议的。

#2


应用说类似于指针传参。

引用 楼主 u013279563 的回复:
C++中引入了按 引用传参的机制,实际上就是对实参起了一个别名,达到直接控制实参的目的。与按 传参的方法相比,避免了开辟实参副本的时空开销。还可以可以通过const对是否允许改变实参进行控制。
我想问问各位大神,这样看来“按引用传参”是不是可以完全取代“按值传参”了呢?如果真的这样。按值传参的机制还有什么存在的意义呢?本人小菜,求指点!

#3


用户自定义的类型最好用引用传参,这样可以避免不必要的构造函数和析构函数调用,但是对于像int,long,char一类的简单类型,按值传参也没有太多的开销,此时两种都可以

#4


如果都按引用传参的话需要注意实参被无意修改的可能(需要随时加const来限定),引用传参的实际意义多在参数较大时,降低系统开销

#5


引用 3 楼 waterSStreaming 的回复:
用户自定义的类型最好用引用传参,这样可以避免不必要的构造函数和析构函数调用,但是对于像int,long,char一类的简单类型,按值传参也没有太多的开销,此时两种都可以
这样可以避免不必要的构造函数和析构函数调用??求解释

#6


引用传参用得太多,代码看着别扭,对于对象较大,减少复制副本开支还是用引用好,个人愚见..

#7


传值还是有用处的
需要改变传入后的值,而无须改变传入前的值。 这样的需求引用传参就办不到

#8


引用传参一般是针对于类或者大的结构体,这样可以减少对象复制、创建时间。而引用看起来会比较别扭,也会让代码变的难以理解,所以一般基础类型(int , float  等等)都直接采用值传参,对于这种基础数据类型,采用引用或值传递的效率是差不多的。

如果总是采用引用传参,会导致一些问题,比如说,你要引用的那个对象的声明周期结束了呢?如果是值传递,就不用管先前那个对象是否还活着,如果是引用,就得注意这些问题。

#9


《Effective C++》条款22:尽量用"传引用"代替"传值"
http://riddickbryant.iteye.com/blog/569055

引用几乎都是通过指针来实现的,所以通过引用传递对象实际上是传递指针。因此,如果是一个很小的对象——例如int——传值实际上会比传引用更高效。

#10


引用传参和指针传参差不多!如果仅需要有一个返回值的话,按值传参的效率应该会更高些!如果不加const 不至于对主函数的值进行修改!
同意楼上说的,对于内置类型,按值传参的效率更高些!

#11


相当于指针的复制,但远远比对象的复制好,因为32位机指针才4字节,一般对象远远不只4字节。

#12


引用传递,只是明面上,没有使用值传递,值传递本身是不可避免的
编译器,暗地里通过指针(或者其他可以替代指针的数据类型)的值传递,替换了引用传递
所以引用传递,实质上是地址传递,别名这东西只是概念,是一种抽象,别名是没法传递的。

别名,可不是真实的数据类型哦。

因为,函数传递参数需要,数据复制,所以明的暗的值传递,不可避免。
如果采用全局变量,传递参数,那么函数调用,就可以避免直接数据复制了。
不过使用全局变量,这,,,引入的问题,比解决的问题还多。

引用的高效,在于对大的数据,不用直接的复制数据。
函数调用的语义,接近于值传递的语义

即 void fun(const A & a) ; 和 void fun (int a) ;的调用形式一致都是 fun(a);

#13


引用 5 楼 u013279563 的回复:
Quote: 引用 3 楼 waterSStreaming 的回复:

用户自定义的类型最好用引用传参,这样可以避免不必要的构造函数和析构函数调用,但是对于像int,long,char一类的简单类型,按值传参也没有太多的开销,此时两种都可以
这样可以避免不必要的构造函数和析构函数调用??求解释


#include <cstdio>
#include <iostream>
#include <vector>

using namespace std;

struct node
{
int *p1;
double *p2;

node()
{
p1 = new int();
p2 = new double();

*p1 = 0;
*p2 = 0.0;

cout << "Execute node's constructor." << endl;
}

node(const node &_node)
{
cout << "Execute node's copy constructor." << endl;

if(this == &_node)
{
return;
}

this->p1 = new int();
this->p2 = new double();

*p1 = *_node.p1;
*p2 = *_node.p2;
}

node& operator=(const node &_node)
{
cout << "Execute node's assignment operator function." << endl;

if(this == &_node)
{
return *this;
}

this->p1 = new int();
this->p2 = new double();

*p1 = *_node.p1;
*p2 = *_node.p2;

return *this;
}

~node()
{
delete p1;
delete p2;

p1 = 0;
p2 = 0;
}
};

void displayNode1(node _p)
{
cout << (*_p.p1) << endl;
cout << (*_p.p2) << endl;
}

void displayNode2(node &_p)
{
cout << (*_p.p1) << endl;
cout << (*_p.p2) << endl;
}

int main()
{
node p1;
cout << "Execute the display function not using reference." << endl;
displayNode1(p1);

node p2;
cout << "Execute the display function using reference." << endl;
displayNode2(p2);
return 0;
}

输出为

Execute node's constructor.
Execute the display function not using reference.
Execute node's copy constructor.
0
0
Execute node's constructor.
Execute the display function using reference.
0
0

#14


对于外界不希望值被修改,而函数内部会修改参数的值的情况。用const& ,函数内部也会再显示构一临时对象。就没必要用引用了。而且一般小的数据类型比如整型、字符型,如果不是为了把参数的值修改了再传出来,一般不会用引用

#15


计算机组成原理→DOS命令→汇编语言→C语言(不包括C++)、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言(包括C++)、架构……

对学习编程者的忠告:
眼过千遍不如手过一遍!
书看千行不如手敲一行!
手敲千行不如单步一行!
单步源代码千行不如单步对应汇编一行!

VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化,这样过一遍不就啥都明白了吗。
对VC来说,所谓‘调试时’就是编译连接通过以后,按F10或F11键单步执行一步以后的时候,或者在某行按F9设了断点后按F5执行停在该断点处的时候。
(Turbo C或Borland C用Turbo Debugger调试,Linux或Unix下用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。)

#16


不要纠结各种常量了,这个世界上唯一不变的就是变化。用API WriteProcessMemory还能修改正运行的其它进程的内存里面的所谓常量呢!

#17


引用 7 楼 xihu1364 的回复:
传值还是有用处的
需要改变传入后的值,而无须改变传入前的值。 这样的需求引用传参就办不到
额,好像是这么回事,能不能距离呢?

#18


引用 9 楼 feihuadao 的回复:
《Effective C++》条款22:尽量用"传引用"代替"传值"
http://riddickbryant.iteye.com/blog/569055

引用几乎都是通过指针来实现的,所以通过引用传递对象实际上是传递指针。因此,如果是一个很小的对象——例如int——传值实际上会比传引用更高效。
我给的链接我看了,可是那个什么“分割问题”我不知很懂!

#19


引用 14 楼 yunchao630 的回复:
对于外界不希望值被修改,而函数内部会修改参数的值的情况。用const& ,函数内部也会再显示构一临时对象。就没必要用引用了。而且一般小的数据类型比如整型、字符型,如果不是为了把参数的值修改了再传出来,一般不会用引用
会吗?求举例!

#20


其实很好理解,假设你要传的是一个Byte类型的变量,这时候用引用还不如传值吧

#21


引用 12 楼 lm_whales 的回复:
引用传递,只是明面上,没有使用值传递,值传递本身是不可避免的
编译器,暗地里通过指针(或者其他可以替代指针的数据类型)的值传递,替换了引用传递
所以引用传递,实质上是地址传递,别名这东西只是概念,是一种抽象,别名是没法传递的。

别名,可不是真实的数据类型哦。

因为,函数传递参数需要,数据复制,所以明的暗的值传递,不可避免。
如果采用全局变量,传递参数,那么函数调用,就可以避免直接数据复制了。
不过使用全局变量,这,,,引入的问题,比解决的问题还多。

引用的高效,在于对大的数据,不用直接的复制数据。
函数调用的语义,接近于值传递的语义

即 void fun(const A & a) ; 和 void fun (int a) ;的调用形式一致都是 fun(a);

这位仁兄说的很详细很全面

#22


引用 15 楼 zhao4zhong1 的回复:
计算机组成原理→DOS命令→汇编语言→C语言(不包括C++)、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言(包括C++)、架构……

对学习编程者的忠告:
眼过千遍不如手过一遍!
书看千行不如手敲一行!
手敲千行不如单步一行!
单步源代码千行不如单步对应汇编一行!

VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化,这样过一遍不就啥都明白了吗。
对VC来说,所谓‘调试时’就是编译连接通过以后,按F10或F11键单步执行一步以后的时候,或者在某行按F9设了断点后按F5执行停在该断点处的时候。
(Turbo C或Borland C用Turbo Debugger调试,Linux或Unix下用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。)

话说,我跳的有点快。直接就学C然后就是C++,对于很么计算机原理不甚了解,对于网络更是一窍不通。。。。怎么破?

#23


引用 20 楼 xiedonghao 的回复:
其实很好理解,假设你要传的是一个Byte类型的变量,这时候用引用还不如传值吧

我可以问为什么吗?

#24


等你以后就知道了,呵呵

#25


zhao4zhong1 的回复总是那么霸气

#26


碰到数组引用就呵呵了

#27


引用 26 楼 bszk81340089 的回复:
碰到数组引用就呵呵了


数组一样有引用形式(不是引用数组中某个元素,而是整个数组),而且恰好是数组不能整体的当作一个参数传给函数。你把他隐式转换成指针再传的话,长度信息将会丢失

#28


传值有这么几个作用:
- 函数内部需要用到改变的传入参数,却不希望源参数的内容被修改
- 值传递会导致忽略实参的cv属性,这样对写函数重载有好处,如果有两个形参的类型一样,而实参传入时的cv属性不同,不至于导致重载匹配的失败
当然如果打算用值传递的话,拷贝开销就是避免不了的问题了。

#29


内置类型建议使用pass by value

#30


如果按值传参,那么在递归函数回溯时就无需手动对参数进行还原。而传引用的话,改变的参数值必须在回溯时手动还原,这很容易出错,这算一个实用型的小意义吧 关于函数的传参问题

#31


像这种需求, 引用就没有这么方便了.

class MyClass
{
    public:
    int  m_a;
}
int fun( MyClass a)
{
       a.m_a = 100;
       return  a.m_a;
}

想使用a, 但是又不想改变外部的a, 但又能在内部直接对a对象的现有数据进行操作. 这时就只能用传值了.
你传引用,或者常引用都不能办到.
当然, 你说我可以在函数内,再定义一个对象, 把引用的对象复制一遍, 愿意这样做, 那我也无话可说.

#32


引用 27 楼 unituniverse2 的回复:
Quote: 引用 26 楼 bszk81340089 的回复:

碰到数组引用就呵呵了


数组一样有引用形式(不是引用数组中某个元素,而是整个数组),而且恰好是数组不能整体的当作一个参数传给函数。你把他隐式转换成指针再传的话,长度信息将会丢失
引用的话,不是只能引用数组的一个元素。如果是传入整个数组不也是传入的是数组的首地址吗?

#33


引用 楼主 u013279563 的回复:
C++中引入了按 引用传参的机制,实际上就是对实参起了一个别名,达到直接控制实参的目的。与按 传参的方法相比,避免了开辟实参副本的时空开销。还可以可以通过const对是否允许改变实参进行控制。
我想问问各位大神,这样看来“按引用传参”是不是可以完全取代“按值传参”了呢?如果真的这样。按值传参的机制还有什么存在的意义呢?本人小菜,求指点!


语法规则而已,传递引用实际还是传递一个指针,只是在函数中按照引用的规则使用传人的参数而已

#34


咋没人将整个互联网内容引用传参给一个函数呢? 关于函数的传参问题

#35


非引用类型的copy-initialization保证对象的复制或转移。如果只传引用,除去函数引用你还可能得自己维护对象的生存期——很多时候明显多此一举。对于C++,传递对象引用特别地强调调用者在乎并且想避免对象的复制初始化——通常是基于开销或者同一性考虑。如果目的不是修改对象(使用左值引用),对象自身没有共享的可变状态,复制开销可以接受,那么没理由使用引用传递;典型地如内建类型的整数。
撇开C++不讲,call by reference相对call by value在很多时候能让调用变得更加简洁——例如Y combinator可以省掉CBV形式的eta conversion。代价类似:变量没法和lexical scope绑定确定生存期。
科普:
http://en.wikipedia.org/wiki/Evaluation_strategy

#36


有很多同胞告诉我:引用传参实际还是传递一个指针,所以对于一些小字节的数据,没必要用“引用传参”。
可是我在网上看到这样的话:传递变量的指针。形参是指针变量,实参是一个变量的地址,调用函数时,形参(指针变量)指向实参变量单元。这种“虚实结合”的方法仍然是“值传递”方式,只是实参的值是变量的地址而已。通过形参指针变量访问主函数中的变量(i和j),并改变它们的值。(这样就能得到正确结果,但是在概念上却是兜了一个圈子,不那么直截了当。)
这段话,明确的指出:引用传参并非传递变量的指针。有没有大神出来,解释下。这两种传参方式又有什么区别呢?

#37


引用 29 楼 derekrose 的回复:
内置类型建议使用pass by value


说法好洋气

#38


引用 28 楼 unituniverse2 的回复:
传值有这么几个作用:
- 函数内部需要用到改变的传入参数,却不希望源参数的内容被修改
- 值传递会导致忽略实参的cv属性,这样对写函数重载有好处,如果有两个形参的类型一样,而实参传入时的cv属性不同,不至于导致重载匹配的失败
当然如果打算用值传递的话,拷贝开销就是避免不了的问题了。

我可以问:cv是什么吗?请原谅我的无知。

#39


引用 38 楼 u013279563 的回复:
Quote: 引用 28 楼 unituniverse2 的回复:

传值有这么几个作用:
- 函数内部需要用到改变的传入参数,却不希望源参数的内容被修改
- 值传递会导致忽略实参的cv属性,这样对写函数重载有好处,如果有两个形参的类型一样,而实参传入时的cv属性不同,不至于导致重载匹配的失败
当然如果打算用值传递的话,拷贝开销就是避免不了的问题了。

我可以问:cv是什么吗?请原谅我的无知。

标准中规定必须有的目前只有const和volatile这两个(就是这个所谓的“cv”)。但是允许编译器 在此基础上再扩展一些(比如大部分机器上需要支持aligned属性),这些扩展的属性和const和volatile一起称作"cv属性"(而不是仅仅const和volatile这两个)

#40


引用 36 楼 u013279563 的回复:
有很多同胞告诉我:引用传参实际还是传递一个指针,所以对于一些小字节的数据,没必要用“引用传参”。
可是我在网上看到这样的话:传递变量的指针。形参是指针变量,实参是一个变量的地址,调用函数时,形参(指针变量)指向实参变量单元。这种“虚实结合”的方法仍然是“值传递”方式,只是实参的值是变量的地址而已。通过形参指针变量访问主函数中的变量(i和j),并改变它们的值。(这样就能得到正确结果,但是在概念上却是兜了一个圈子,不那么直截了当。)
这段话,明确的指出:引用传参并非传递变量的指针。有没有大神出来,解释下。这两种传参方式又有什么区别呢?

CBV和CBR本来就两回事。
只不过在需要保持恒定调用约定以保持公开的二进制兼容性,不进行程序变换为基础的优化的前提下,在实现意义上传递C++内建指针和传递C++内建引用类型的参数生成的代码效果类似。具体会怎么样随实现高兴,和C++本身做了什么(抽象机为基础的基本语义)已经无关了。
“实参的值是变量的地址”纯属扯淡,基本上就没搞清楚值有类型而地址不考虑类型的基本概念。


#41


引用 39 楼 unituniverse2 的回复:
Quote: 引用 38 楼 u013279563 的回复:

Quote: 引用 28 楼 unituniverse2 的回复:

传值有这么几个作用:
- 函数内部需要用到改变的传入参数,却不希望源参数的内容被修改
- 值传递会导致忽略实参的cv属性,这样对写函数重载有好处,如果有两个形参的类型一样,而实参传入时的cv属性不同,不至于导致重载匹配的失败
当然如果打算用值传递的话,拷贝开销就是避免不了的问题了。

我可以问:cv是什么吗?请原谅我的无知。

标准中规定必须有的目前只有const和volatile这两个(就是这个所谓的“cv”)。但是允许编译器 在此基础上再扩展一些(比如大部分机器上需要支持aligned属性),这些扩展的属性和const和volatile一起称作"cv属性"(而不是仅仅const和volatile这两个)

准确地说cv就只是指const和volatile这两个限定符(qualifier) 。其它语法地位相当的限定符不会称为cv。
同样是限定符的,在ISO C中还有restrict和_Atomic。

#42


内置类型还是传值效率高

#43


坐看各大牛人语录,哈哈!!长见识啊

#44


MARK一下,回去慢慢看。。

#45


看各位大神讨论,学习了

#46


看各位大神讨论,学习了

#47


听得我好乱,还有谁有想法。来说啊!

#48


引用 37 楼 u013279563 的回复:
Quote: 引用 29 楼 derekrose 的回复:

内置类型建议使用pass by value


说法好洋气

这些术语还是原始的比较好。

#49


引用 48 楼 lijian19911012 的回复:
Quote: 引用 37 楼 u013279563 的回复:

Quote: 引用 29 楼 derekrose 的回复:

内置类型建议使用pass by value


说法好洋气

这些术语还是原始的比较好。
这个。。我只是个渣渣,不方便评价。只是一开始真么看懂。

#1


你完全用传引用代替值传递没什么问题,《Effective C++》中也是这样建议的。

#2


应用说类似于指针传参。

引用 楼主 u013279563 的回复:
C++中引入了按 引用传参的机制,实际上就是对实参起了一个别名,达到直接控制实参的目的。与按 传参的方法相比,避免了开辟实参副本的时空开销。还可以可以通过const对是否允许改变实参进行控制。
我想问问各位大神,这样看来“按引用传参”是不是可以完全取代“按值传参”了呢?如果真的这样。按值传参的机制还有什么存在的意义呢?本人小菜,求指点!

#3


用户自定义的类型最好用引用传参,这样可以避免不必要的构造函数和析构函数调用,但是对于像int,long,char一类的简单类型,按值传参也没有太多的开销,此时两种都可以

#4


如果都按引用传参的话需要注意实参被无意修改的可能(需要随时加const来限定),引用传参的实际意义多在参数较大时,降低系统开销

#5


引用 3 楼 waterSStreaming 的回复:
用户自定义的类型最好用引用传参,这样可以避免不必要的构造函数和析构函数调用,但是对于像int,long,char一类的简单类型,按值传参也没有太多的开销,此时两种都可以
这样可以避免不必要的构造函数和析构函数调用??求解释

#6


引用传参用得太多,代码看着别扭,对于对象较大,减少复制副本开支还是用引用好,个人愚见..

#7


传值还是有用处的
需要改变传入后的值,而无须改变传入前的值。 这样的需求引用传参就办不到

#8


引用传参一般是针对于类或者大的结构体,这样可以减少对象复制、创建时间。而引用看起来会比较别扭,也会让代码变的难以理解,所以一般基础类型(int , float  等等)都直接采用值传参,对于这种基础数据类型,采用引用或值传递的效率是差不多的。

如果总是采用引用传参,会导致一些问题,比如说,你要引用的那个对象的声明周期结束了呢?如果是值传递,就不用管先前那个对象是否还活着,如果是引用,就得注意这些问题。

#9


《Effective C++》条款22:尽量用"传引用"代替"传值"
http://riddickbryant.iteye.com/blog/569055

引用几乎都是通过指针来实现的,所以通过引用传递对象实际上是传递指针。因此,如果是一个很小的对象——例如int——传值实际上会比传引用更高效。

#10


引用传参和指针传参差不多!如果仅需要有一个返回值的话,按值传参的效率应该会更高些!如果不加const 不至于对主函数的值进行修改!
同意楼上说的,对于内置类型,按值传参的效率更高些!

#11


相当于指针的复制,但远远比对象的复制好,因为32位机指针才4字节,一般对象远远不只4字节。

#12


引用传递,只是明面上,没有使用值传递,值传递本身是不可避免的
编译器,暗地里通过指针(或者其他可以替代指针的数据类型)的值传递,替换了引用传递
所以引用传递,实质上是地址传递,别名这东西只是概念,是一种抽象,别名是没法传递的。

别名,可不是真实的数据类型哦。

因为,函数传递参数需要,数据复制,所以明的暗的值传递,不可避免。
如果采用全局变量,传递参数,那么函数调用,就可以避免直接数据复制了。
不过使用全局变量,这,,,引入的问题,比解决的问题还多。

引用的高效,在于对大的数据,不用直接的复制数据。
函数调用的语义,接近于值传递的语义

即 void fun(const A & a) ; 和 void fun (int a) ;的调用形式一致都是 fun(a);

#13


引用 5 楼 u013279563 的回复:
Quote: 引用 3 楼 waterSStreaming 的回复:

用户自定义的类型最好用引用传参,这样可以避免不必要的构造函数和析构函数调用,但是对于像int,long,char一类的简单类型,按值传参也没有太多的开销,此时两种都可以
这样可以避免不必要的构造函数和析构函数调用??求解释


#include <cstdio>
#include <iostream>
#include <vector>

using namespace std;

struct node
{
int *p1;
double *p2;

node()
{
p1 = new int();
p2 = new double();

*p1 = 0;
*p2 = 0.0;

cout << "Execute node's constructor." << endl;
}

node(const node &_node)
{
cout << "Execute node's copy constructor." << endl;

if(this == &_node)
{
return;
}

this->p1 = new int();
this->p2 = new double();

*p1 = *_node.p1;
*p2 = *_node.p2;
}

node& operator=(const node &_node)
{
cout << "Execute node's assignment operator function." << endl;

if(this == &_node)
{
return *this;
}

this->p1 = new int();
this->p2 = new double();

*p1 = *_node.p1;
*p2 = *_node.p2;

return *this;
}

~node()
{
delete p1;
delete p2;

p1 = 0;
p2 = 0;
}
};

void displayNode1(node _p)
{
cout << (*_p.p1) << endl;
cout << (*_p.p2) << endl;
}

void displayNode2(node &_p)
{
cout << (*_p.p1) << endl;
cout << (*_p.p2) << endl;
}

int main()
{
node p1;
cout << "Execute the display function not using reference." << endl;
displayNode1(p1);

node p2;
cout << "Execute the display function using reference." << endl;
displayNode2(p2);
return 0;
}

输出为

Execute node's constructor.
Execute the display function not using reference.
Execute node's copy constructor.
0
0
Execute node's constructor.
Execute the display function using reference.
0
0

#14


对于外界不希望值被修改,而函数内部会修改参数的值的情况。用const& ,函数内部也会再显示构一临时对象。就没必要用引用了。而且一般小的数据类型比如整型、字符型,如果不是为了把参数的值修改了再传出来,一般不会用引用

#15


计算机组成原理→DOS命令→汇编语言→C语言(不包括C++)、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言(包括C++)、架构……

对学习编程者的忠告:
眼过千遍不如手过一遍!
书看千行不如手敲一行!
手敲千行不如单步一行!
单步源代码千行不如单步对应汇编一行!

VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化,这样过一遍不就啥都明白了吗。
对VC来说,所谓‘调试时’就是编译连接通过以后,按F10或F11键单步执行一步以后的时候,或者在某行按F9设了断点后按F5执行停在该断点处的时候。
(Turbo C或Borland C用Turbo Debugger调试,Linux或Unix下用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。)

#16


不要纠结各种常量了,这个世界上唯一不变的就是变化。用API WriteProcessMemory还能修改正运行的其它进程的内存里面的所谓常量呢!

#17


引用 7 楼 xihu1364 的回复:
传值还是有用处的
需要改变传入后的值,而无须改变传入前的值。 这样的需求引用传参就办不到
额,好像是这么回事,能不能距离呢?

#18


引用 9 楼 feihuadao 的回复:
《Effective C++》条款22:尽量用"传引用"代替"传值"
http://riddickbryant.iteye.com/blog/569055

引用几乎都是通过指针来实现的,所以通过引用传递对象实际上是传递指针。因此,如果是一个很小的对象——例如int——传值实际上会比传引用更高效。
我给的链接我看了,可是那个什么“分割问题”我不知很懂!

#19


引用 14 楼 yunchao630 的回复:
对于外界不希望值被修改,而函数内部会修改参数的值的情况。用const& ,函数内部也会再显示构一临时对象。就没必要用引用了。而且一般小的数据类型比如整型、字符型,如果不是为了把参数的值修改了再传出来,一般不会用引用
会吗?求举例!

#20


其实很好理解,假设你要传的是一个Byte类型的变量,这时候用引用还不如传值吧

#21


引用 12 楼 lm_whales 的回复:
引用传递,只是明面上,没有使用值传递,值传递本身是不可避免的
编译器,暗地里通过指针(或者其他可以替代指针的数据类型)的值传递,替换了引用传递
所以引用传递,实质上是地址传递,别名这东西只是概念,是一种抽象,别名是没法传递的。

别名,可不是真实的数据类型哦。

因为,函数传递参数需要,数据复制,所以明的暗的值传递,不可避免。
如果采用全局变量,传递参数,那么函数调用,就可以避免直接数据复制了。
不过使用全局变量,这,,,引入的问题,比解决的问题还多。

引用的高效,在于对大的数据,不用直接的复制数据。
函数调用的语义,接近于值传递的语义

即 void fun(const A & a) ; 和 void fun (int a) ;的调用形式一致都是 fun(a);

这位仁兄说的很详细很全面

#22


引用 15 楼 zhao4zhong1 的回复:
计算机组成原理→DOS命令→汇编语言→C语言(不包括C++)、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言(包括C++)、架构……

对学习编程者的忠告:
眼过千遍不如手过一遍!
书看千行不如手敲一行!
手敲千行不如单步一行!
单步源代码千行不如单步对应汇编一行!

VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化,这样过一遍不就啥都明白了吗。
对VC来说,所谓‘调试时’就是编译连接通过以后,按F10或F11键单步执行一步以后的时候,或者在某行按F9设了断点后按F5执行停在该断点处的时候。
(Turbo C或Borland C用Turbo Debugger调试,Linux或Unix下用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。)

话说,我跳的有点快。直接就学C然后就是C++,对于很么计算机原理不甚了解,对于网络更是一窍不通。。。。怎么破?

#23


引用 20 楼 xiedonghao 的回复:
其实很好理解,假设你要传的是一个Byte类型的变量,这时候用引用还不如传值吧

我可以问为什么吗?

#24


等你以后就知道了,呵呵

#25


zhao4zhong1 的回复总是那么霸气

#26


碰到数组引用就呵呵了

#27


引用 26 楼 bszk81340089 的回复:
碰到数组引用就呵呵了


数组一样有引用形式(不是引用数组中某个元素,而是整个数组),而且恰好是数组不能整体的当作一个参数传给函数。你把他隐式转换成指针再传的话,长度信息将会丢失

#28


传值有这么几个作用:
- 函数内部需要用到改变的传入参数,却不希望源参数的内容被修改
- 值传递会导致忽略实参的cv属性,这样对写函数重载有好处,如果有两个形参的类型一样,而实参传入时的cv属性不同,不至于导致重载匹配的失败
当然如果打算用值传递的话,拷贝开销就是避免不了的问题了。

#29


内置类型建议使用pass by value

#30


如果按值传参,那么在递归函数回溯时就无需手动对参数进行还原。而传引用的话,改变的参数值必须在回溯时手动还原,这很容易出错,这算一个实用型的小意义吧 关于函数的传参问题

#31


像这种需求, 引用就没有这么方便了.

class MyClass
{
    public:
    int  m_a;
}
int fun( MyClass a)
{
       a.m_a = 100;
       return  a.m_a;
}

想使用a, 但是又不想改变外部的a, 但又能在内部直接对a对象的现有数据进行操作. 这时就只能用传值了.
你传引用,或者常引用都不能办到.
当然, 你说我可以在函数内,再定义一个对象, 把引用的对象复制一遍, 愿意这样做, 那我也无话可说.

#32


引用 27 楼 unituniverse2 的回复:
Quote: 引用 26 楼 bszk81340089 的回复:

碰到数组引用就呵呵了


数组一样有引用形式(不是引用数组中某个元素,而是整个数组),而且恰好是数组不能整体的当作一个参数传给函数。你把他隐式转换成指针再传的话,长度信息将会丢失
引用的话,不是只能引用数组的一个元素。如果是传入整个数组不也是传入的是数组的首地址吗?

#33


引用 楼主 u013279563 的回复:
C++中引入了按 引用传参的机制,实际上就是对实参起了一个别名,达到直接控制实参的目的。与按 传参的方法相比,避免了开辟实参副本的时空开销。还可以可以通过const对是否允许改变实参进行控制。
我想问问各位大神,这样看来“按引用传参”是不是可以完全取代“按值传参”了呢?如果真的这样。按值传参的机制还有什么存在的意义呢?本人小菜,求指点!


语法规则而已,传递引用实际还是传递一个指针,只是在函数中按照引用的规则使用传人的参数而已

#34


咋没人将整个互联网内容引用传参给一个函数呢? 关于函数的传参问题

#35


非引用类型的copy-initialization保证对象的复制或转移。如果只传引用,除去函数引用你还可能得自己维护对象的生存期——很多时候明显多此一举。对于C++,传递对象引用特别地强调调用者在乎并且想避免对象的复制初始化——通常是基于开销或者同一性考虑。如果目的不是修改对象(使用左值引用),对象自身没有共享的可变状态,复制开销可以接受,那么没理由使用引用传递;典型地如内建类型的整数。
撇开C++不讲,call by reference相对call by value在很多时候能让调用变得更加简洁——例如Y combinator可以省掉CBV形式的eta conversion。代价类似:变量没法和lexical scope绑定确定生存期。
科普:
http://en.wikipedia.org/wiki/Evaluation_strategy

#36


有很多同胞告诉我:引用传参实际还是传递一个指针,所以对于一些小字节的数据,没必要用“引用传参”。
可是我在网上看到这样的话:传递变量的指针。形参是指针变量,实参是一个变量的地址,调用函数时,形参(指针变量)指向实参变量单元。这种“虚实结合”的方法仍然是“值传递”方式,只是实参的值是变量的地址而已。通过形参指针变量访问主函数中的变量(i和j),并改变它们的值。(这样就能得到正确结果,但是在概念上却是兜了一个圈子,不那么直截了当。)
这段话,明确的指出:引用传参并非传递变量的指针。有没有大神出来,解释下。这两种传参方式又有什么区别呢?

#37


引用 29 楼 derekrose 的回复:
内置类型建议使用pass by value


说法好洋气

#38


引用 28 楼 unituniverse2 的回复:
传值有这么几个作用:
- 函数内部需要用到改变的传入参数,却不希望源参数的内容被修改
- 值传递会导致忽略实参的cv属性,这样对写函数重载有好处,如果有两个形参的类型一样,而实参传入时的cv属性不同,不至于导致重载匹配的失败
当然如果打算用值传递的话,拷贝开销就是避免不了的问题了。

我可以问:cv是什么吗?请原谅我的无知。

#39


引用 38 楼 u013279563 的回复:
Quote: 引用 28 楼 unituniverse2 的回复:

传值有这么几个作用:
- 函数内部需要用到改变的传入参数,却不希望源参数的内容被修改
- 值传递会导致忽略实参的cv属性,这样对写函数重载有好处,如果有两个形参的类型一样,而实参传入时的cv属性不同,不至于导致重载匹配的失败
当然如果打算用值传递的话,拷贝开销就是避免不了的问题了。

我可以问:cv是什么吗?请原谅我的无知。

标准中规定必须有的目前只有const和volatile这两个(就是这个所谓的“cv”)。但是允许编译器 在此基础上再扩展一些(比如大部分机器上需要支持aligned属性),这些扩展的属性和const和volatile一起称作"cv属性"(而不是仅仅const和volatile这两个)

#40


引用 36 楼 u013279563 的回复:
有很多同胞告诉我:引用传参实际还是传递一个指针,所以对于一些小字节的数据,没必要用“引用传参”。
可是我在网上看到这样的话:传递变量的指针。形参是指针变量,实参是一个变量的地址,调用函数时,形参(指针变量)指向实参变量单元。这种“虚实结合”的方法仍然是“值传递”方式,只是实参的值是变量的地址而已。通过形参指针变量访问主函数中的变量(i和j),并改变它们的值。(这样就能得到正确结果,但是在概念上却是兜了一个圈子,不那么直截了当。)
这段话,明确的指出:引用传参并非传递变量的指针。有没有大神出来,解释下。这两种传参方式又有什么区别呢?

CBV和CBR本来就两回事。
只不过在需要保持恒定调用约定以保持公开的二进制兼容性,不进行程序变换为基础的优化的前提下,在实现意义上传递C++内建指针和传递C++内建引用类型的参数生成的代码效果类似。具体会怎么样随实现高兴,和C++本身做了什么(抽象机为基础的基本语义)已经无关了。
“实参的值是变量的地址”纯属扯淡,基本上就没搞清楚值有类型而地址不考虑类型的基本概念。


#41


引用 39 楼 unituniverse2 的回复:
Quote: 引用 38 楼 u013279563 的回复:

Quote: 引用 28 楼 unituniverse2 的回复:

传值有这么几个作用:
- 函数内部需要用到改变的传入参数,却不希望源参数的内容被修改
- 值传递会导致忽略实参的cv属性,这样对写函数重载有好处,如果有两个形参的类型一样,而实参传入时的cv属性不同,不至于导致重载匹配的失败
当然如果打算用值传递的话,拷贝开销就是避免不了的问题了。

我可以问:cv是什么吗?请原谅我的无知。

标准中规定必须有的目前只有const和volatile这两个(就是这个所谓的“cv”)。但是允许编译器 在此基础上再扩展一些(比如大部分机器上需要支持aligned属性),这些扩展的属性和const和volatile一起称作"cv属性"(而不是仅仅const和volatile这两个)

准确地说cv就只是指const和volatile这两个限定符(qualifier) 。其它语法地位相当的限定符不会称为cv。
同样是限定符的,在ISO C中还有restrict和_Atomic。

#42


内置类型还是传值效率高

#43


坐看各大牛人语录,哈哈!!长见识啊

#44


MARK一下,回去慢慢看。。

#45


看各位大神讨论,学习了

#46


看各位大神讨论,学习了

#47


听得我好乱,还有谁有想法。来说啊!

#48


引用 37 楼 u013279563 的回复:
Quote: 引用 29 楼 derekrose 的回复:

内置类型建议使用pass by value


说法好洋气

这些术语还是原始的比较好。

#49


引用 48 楼 lijian19911012 的回复:
Quote: 引用 37 楼 u013279563 的回复:

Quote: 引用 29 楼 derekrose 的回复:

内置类型建议使用pass by value


说法好洋气

这些术语还是原始的比较好。
这个。。我只是个渣渣,不方便评价。只是一开始真么看懂。