gpt4 book ai didi

将对象传递给它时方法签名之间的 C++ 区别

转载 作者:行者123 更新时间:2023-11-30 03:59:40 27 4
gpt4 key购买 nike

我发现在 C++ 中可以通过三种不同的方式将对象传递给函数。假设我的类(class)是这样的:

class Test {
int i;
public:
Test(int x);
int getX();
void setX(int num);
};

Test::Test(int x) {
i = x;
}

int Test::getX() {
return i;
}

void Test::setX(int num) {
i = num;
}

这三个签名可以将类 Test 的对象传递给方法:

void temp(Test obj) {
obj.setX(100);
}

void perm(Test *obj) {
obj->setX(150);
}

void noidea(Test &obj) {
obj.setX(150);
}

事实证明,第二个和第三个方法会影响调用者,即在函数内部修改的同一个对象,而在第一个方法中,它只是按位复制对象,因此不会影响调用者(如果拷贝修改指针成员或资源,它会影响调用者)。

除此之外,签名还有其他区别吗?

有人可以解释第三个签名吗?我可以理解第二个,你称它为 int retVal = perm(&object),其中 object 属于 Test 类。该地址由函数参数中的obj捕获,因为它是类Test的对象的地址,类型是指向类Test的对象的指针,因此使用间接访问其成员。但是第三个签名是如何工作的,调用noidea(object)时传递给它的到底是什么,函数参数objint的类型到底是什么?

最佳答案

第三个调用约定在技术上与第二个调用约定类似:编译器将在后台生成代码来获取对象的地址。从技术上讲,引用就像一个 const 指针,但您不必取消引用它。

虽然语义并不完全相似:

  • 在第三种方法中,您确实必须提供一个对象作为参数,而在第二种方法中,您仍然可以进行一些指针运算和函数调用来确定地址
  • 在第三个中你不能传递一个nullptr
  • 事实上,对于引用,一切都像使用另一个名称的原始对象一样工作。

有关语义差异的更多信息,请查看示例 here .

实验演示:

如果有进一步的兴趣,这里是为调用生成的汇编代码:

; 45   :    temp(t);            ; Call by value:  
mov eax, DWORD PTR _t$[ebp] ; Moves the content of the object
push eax ; Put it on stack
call ?temp@@YAXVTest@@@Z ; Call temp
add esp, 4
; 46 : perm(&t); ; Call by address:
lea eax, DWORD PTR _t$[ebp] ; Moves the adress of the object
push eax ; Put it on the stack
call ?perm@@YAXPAVTest@@@Z ; Call perm
add esp, 4
; 47 : noidea(t); ; Call by reference:
lea eax, DWORD PTR _t$[ebp] ; Exactly the same code as with pointes
push eax
call ?noidea@@YAXAAVTest@@@Z ; but with noidea
add esp, 4

perm() 生成的汇编代码与为 noidea() 生成的汇编代码完全相同(除了值 100 和 150)。我没有在这里展示,但如果你有兴趣让我知道。

对于语义差异的实验:尝试在 perm()noidea() 的末尾做 obj++; : 第一个会编译(增加 obj 指针)而第二个不会(你不能增加对象本身,因为 ++ 运算符没有为类 Test 定义)。

关于将对象传递给它时方法签名之间的 C++ 区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26816545/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com