值传递 和 引用传递

162 阅读2分钟

相同点:两者都是在被调用函数中的栈区开辟一个空间,往这块空间填入一个值

值传递

  • 值传递:在函数调用时候,会触发一次参数的拷贝动作,因此对参数的修改不会影响原始的值,如果是较大的对象,复制整个对象,效率较低
void modify_value(int value) {
    value = 100; // 只会修改函数内部的副本,不会影响原始变量
}

int main() {
    int a = 20;
    modify_value(a);
    std::cout << a; // 20,没变
    return 0;
}

引用传递

  • 引用传递:函数调用时,函数接收的就是参数的引用,不会触发参数的拷贝动作,效率较高,但对参数的修改会直接作用于原始的值
void modify_value(int& value) {
    value = 100; // 修改引用指向的原始变量
}

int main() {
    int a = 20;
    modify_value(a);
    std::cout << a; // 100,因为是引用传递,所以这里已经改为了100
    return 0;
}


从编译的角度看,生成符号表的时候,会在符号表中填入变量名和对应的地址。值传递的形参对应的地址是实参变量的地址,而这个地址中的内容是可以改变的。而引用变量名对应的地址是引用对象的地址,符号表一经生成无法改变,所以引用变量不能更改引用的对象。

实际使用

什么场景下使用引用传递?

🔥 避免不必要的数据拷贝:对于比较大的对象参数 (比如 std::vectorstd::stringstd::list),因为拷贝会导致大量的内存和时间开销。而引用传递可以避免这些开销。 允许函数修改实参原始值:有时候,我们就是希望函数能够直接修改传入的变量值,这时使用引用传递很合理。

什么场景下使用值传递?

🔥 小型数据结构:对于 int、char、double、float这种基础数据类型,可以直接简单的使用值传递。 不希望函数修改实参:有时候,我们需要修改变量数据,但是又不希望修改原始值,可以考虑使用值传递。

在实际代码中,为了减少拷贝,我们通过是使用 const auto &,防止传递的数据发生变化,但是有时候 const 也会出现点问题,有时候也会去掉,但是这个需要我们函数里面没对实参作出修改,具体问题具体分析