C++按值传递,难道不应该将两个变量的memory_addresses复制并绑定到不同的位置吗?

C++ Pass-by-value, shouldn't the memory_addresses of the two variables be copied and binded into different places?

提问人:ian 提问时间:7/14/2023 最后编辑:ian 更新时间:7/15/2023 访问量:89

问:

我正在练习 C++,并面对按值传递/引用主题。我从 BroCode 中学到的是,当我们通过参数的值调用交换函数时,它们的两个memory_addresses都将与原始函数不同。

#include <iostream>

using std::cout;
using std::endl;

void swap_byValue(int dog, int cat);
void swap_byReference(int &dog, int &cat);
void print(int dog, int cat);

int main(){
    int dog = 100;
    int cat = 999;

    cout << "*****************************" << endl
         << "*  variable_name  *  value  *" << "      (memory_address)" << endl;

    print(dog, cat);

    swap_byValue(dog, cat);
    print(dog, cat);
    return 0;
}

void swap_byValue(int dog, int cat){
    int temp;
    temp = dog;
    dog = cat;
    cat = temp;
}
void swap_byReference(int &dog, int &cat){
    int temp;
    temp = dog;
    dog = cat;
    cat = temp;
}

void print(int dog, int cat){
    cout << "*****************************" << "----->  " << &dog << endl
         << "*       dog       *   " << dog << "   *" <<endl
         << "*****************************" << "----->  " << &cat << endl
         << "*       cat       *   " << cat << "   *" <<endl; 
}

运行后的结果如下:

*****************************
*  variable_name  *  value  *      (memory_address)
*****************************----->  0x42295ffc30
*       dog       *   100   *
*****************************----->  0x42295ffc38
*       cat       *   999   *
*****************************----->  0x42295ffc30
*       dog       *   100   *
*****************************----->  0x42295ffc38
*       cat       *   999   *

但是变量 dog(交换前)的内存地址不应该与变量 dog(交换后)不同吗?他们现在都0x42295ffc30。我是否误解了什么或做错了什么?多谢。

C++ 内存地址 按值传递

评论

5赞 πάντα ῥεῖ 7/14/2023
void swap_byValue(int dog, int cat)根本没有任何效果,甚至可能被编译器优化掉。 输出任意堆栈地址。print()
2赞 Alan Birtles 7/14/2023
不能更改引用指向的地址,也不能更改局部变量的地址
2赞 Yksisarvinen 7/14/2023
inside 的地址将与 中的地址不同,因为它将被复制。in 的地址将与 in 的地址相同,因为 reference 基本上是变量的别名。dogswap_byValuemaindogswap_byReferencedogmain
3赞 user4581301 7/14/2023
无论如何,买一本好书。您无法从 6 小时的视频中学习 C++。要学的东西实在太多了。学会有效地使用 C++ 需要几个月的时间,而擅长它需要数年的时间。
2赞 463035818_is_not_an_ai 7/14/2023
我认为毫无疑问,您根据从视频中学到的错误概念编写了代码。不要被试图教你一门语言的随机家伙所愚弄。使用书籍和/或适当的课程

答:

1赞 463035818_is_not_an_ai 7/14/2023 #1

你得到的结果是意料之中的。无法更改对象的地址。例如,可以做的是复制一个对象,然后您在不同的地址有一个新对象,而旧对象位于同一地址。另一方面,引用不会创建新对象,它只是引用原始对象,因此具有相同的地址。

调用没有任何效果,并且会交换参数的值。您实际应该使用的是交换两个变量的值。void swap_byValue(int dog, int cat)void swap_byReference(int &dog, int &cat)std::swap

您打印的地址是函数局部变量和 的地址。您可以通过使用不同的名称来避免混淆:printdogcat

void print(int a, int b){
    cout << "*****************************" << "----->  " << &a << "\n"
         << "*       a         *   " << a << "   *\n"
         << "*****************************" << "----->  " << &b << "\n"
         << "*       b       *   " << b << "   *\n"; 
}

这将打印两个变量的地址,它们是传递给函数的参数的副本。当您调用该函数两次或更多次时,它们可能会碰巧最终位于内存中的同一位置。这是可能的,因为在函数返回后,它们就消失了。ab

如果打印 和 in 的地址,您还将看到它们在交换后不会更改。dogcatmain

我只能猜到你误会了什么,也许你想看这个:

#include <iostream>

void by_value(int x) { std::cout << "by_value: " << &x << "\n"; }
void by_ref(int& y) { std::cout << "by_ref: " << &y << "\n"; }

int main() {
    int z = 42;
    std::cout << "in main: " << &z << "\n";
    by_value(z);
    by_ref(z);
}

可能的输出

in main: 0x7ffca8f5989c
by_value: 0x7ffca8f5987c
by_ref: 0x7ffca8f5989c

zin 和 in 确实具有相同的地址,因为它是同一个对象。 是对 的引用。引用的地址是原始对象的地址。 in 具有不同的地址,因为它是副本。mainyby_refyzxby_value

我从 BroCode 中学到的是,当我们通过参数的值调用交换函数时,它们的两个memory_addresses都将与原始函数不同。

这是不正确的。

评论

0赞 ian 7/15/2023
先生,非常感谢!我现在知道问题出在 print() 函数上,因为如果我调用 print(),毕竟它仍然调用 main() 中的局部变量!非常感谢!
3赞 Jerry Coffin 7/14/2023 #2

我不会在地址方面考虑那么多。

当您按值传递参数时,该函数将获得您传递的任何参数的副本。因此,当您进行交换时,它只是交换自己的 to 值副本。

当你通过引用传递时,你得到的东西基本上只是原始值的别名。因此,当您交换这些值时,原始值会被交换。