我对按值调用和按引用调用const之间的差异感到有点困惑。有人可以向我解释一下。例如,它们是否都可以防止更改调用者参数,它们是否适用于所有对象大小,是在一个不复制时复制参数,还是在复制时使用更多内存?
答案 0 :(得分:6)
他们都防止改变调用者参数
按值传递会创建调用者提供的参数的副本,因此无论函数做什么,它都会在单独的对象上执行。这意味着永远不会触及原始对象,因此在这种情况下答案是“是”。
另一方面,通过引用传递给const
,让函数引用调用者提供的同一个对象,但它不会让该函数修改它... 除非(正如Luchian Grigore在评论中正确评论的那样)函数的实现者使用const_cast<>
来抛弃引用中的const
- 这是只有知道它才能安全地完成的事情绑定到引用的对象 not 声明为const
类型(否则,您将获得未定义的行为)。
由于这似乎不是考虑您的问题的最可能的情况,并且考虑到通常接受对const
的引用表示承诺该参数将不会被触及,那么答案是,只要我们假设这个承诺得到满足,通过引用传递const
将不会改变调用者提供的参数。所以答案再次是“是” - 我在上面提到的警告。
它们对所有对象大小都很快
不。虽然您应该首先定义“快速”。如果传递的对象类型复制(或移动,如果执行移动而不是复制),则传递的对象类型可能很慢。无论您传递的值的类型是什么,通过引用传递总是会花费相同的(地址的大小)。
请注意,在某些体系结构和某些数据类型(如char
)上传递值可能比通过引用传递更快,而对于足够大的UDT则相反。
在制作副本时会占用更多内存吗?
由于其中只有一个人正在制作副本,因此问题有一个明显的答案。
答案 1 :(得分:0)
主要区别在于传递const
引用(或非const)不会复制参数。 (副本实际上受复制省略限制,但理论上它是传递给值时传递给函数的副本)
在某些情况下,传递值同样快,甚至更快(通常当对象最多是寄存器的大小时)。您通常按值传递基本类型,通过引用传递类类型。
当通过const
引用时,您仍然可以通过强制转换const来修改原始值(通过const_cast
),但如果原始值为const
,则会导致未定义的行为
答案 2 :(得分:0)
按值调用将复制它确实保护调用者参数的对象的所有元素,因为如果要更改某些内容,它只是您正在更改的副本。
通过const引用调用不会复制元素,但由于“const”它将保护调用者的参数。
你const引用。
答案 3 :(得分:0)
我想你的意思是:
之间的区别void Fn1(MyType x);
和
void Fn2(const MyType& x);
在前一种情况下,始终会创建对象的副本,这会使其变慢,特别是如果类型具有非平凡的构造函数。原始对象不受函数中对副本所做的任何更改的影响,但可以更改副本本身。
后一个示例不会创建副本,通常会更快。在函数内部,只能在参数上调用const函数(除非你采用像去掉constness这样的脏技巧),从而保证不会修改对象。
重要提示:本讨论不涉及具有特殊语义的类型,如智能指针。在这种情况下,按值调用仍然允许您更改逻辑上相同的对象,即不是智能ptr实例本身,而是它指向的对象。
以下是您问题的答案:
答案 4 :(得分:0)
值得一提的另一点是,按引用调用函数将转换为内联函数。