使用按引用传递时,对象的内存量是多少? 我认为使用pass by reference不会复制对象,也不会有堆栈对象的大小。 在下面的代码中,似乎对象的整个大小被推入堆栈,无论它是引用还是值。
"John Smith"
输出:
#include <iostream>
#include <stdint.h>
struct structWithSize_s{
char data[1024*2];
};
void usePassPointer(structWithSize_s *t,uint64_t addr){
int i;
std::cout << "usePassPointer: stack: " << std::hex << &i
<< std::dec << " size on stack: " << addr-uint64_t(&i) << std::endl;
i = int(t->data[0]);
}
void usePassByValue(structWithSize_s t,uint64_t addr){
int i;
std::cout << "usePassByValue: stack: " << std::hex << &i
<< std::dec << " size on stack: " << addr-uint64_t(&i) << std::endl;
i = int(t.data[0]);
usePassPointer(&t,uint64_t(&i));
}
void usePassByRef(structWithSize_s &t,uint64_t addr){
int i;
std::cout << "usePassByRef: stack: " << std::hex << &i
<< std::dec << " size on stack: " << addr-uint64_t(&i) << std::endl;
i = int(t.data[0]);
usePassByValue(t,uint64_t(&i));
}
int main(void){
int i;
std::cout << "Base Stack: " << std::hex << &i << std::dec << std::endl;
structWithSize_s t;
std::cout << "Sizeof(t): " << sizeof(t) << std::endl;
usePassByRef(t,uint64_t(&i));
char d;
std::cin >> d;
return 0;
}
答案 0 :(得分:4)
你的测试堆栈大小的方法是......不可靠,温和地说。
为什么不直接去马的嘴巴:
让我们设置场景:
struct X {
char data[1024];
};
void by_value(X x);
void by_ref(X& x);
void by_ptr(X* x);
void test_by_value()
{
X x;
by_value(x);
}
void test_by_ref()
{
X x;
by_ref(x);
}
void test_by_ptr()
{
X x;
by_ptr(&x);
}
现在让我们看看我们实际拥有的东西:
test_by_value(): # @test_by_value()
sub rsp, 2056 // <-- stack increase
lea rsi, [rsp + 1032]
mov ecx, 128
mov rdi, rsp
rep movsq
call by_value(X)
add rsp, 2056
ret
test_by_ref(): # @test_by_ref()
sub rsp, 1032 // <-- stack increase
lea rdi, [rsp + 8]
call by_ref(X&)
add rsp, 1032
ret
test_by_ptr(): # @test_by_ptr()
sub rsp, 1032 // <-- stack increase
lea rdi, [rsp + 8]
call by_ptr(X*)
add rsp, 1032
ret
正如您在test_by_value
中看到的那样,堆栈增加了2056,这大约是本地x
变量(1024)的大小+复制参数+其他堆栈恶作剧的大小。< / p>
在test_by_ref
和test_by_ptr
中,堆栈增加1032
,证明对象x
不会在堆栈中重复。
你有:经验证明,通过引用传递不会将堆栈用于整个对象。
回到你的测试方法。在高中和某种程度上的教师,我被展示了#34;堆栈概念&#34;通过以同样的方式做事:观察局部变量的地址并比较它们。
但是我厌恶这种方法。甚至没有谈论可移植性问题。但是除非你非常了解ABI契约以及编译器实现和优化实现(是的,编译器甚至用-O0
进行了一些优化),你得到的结果你并不真正理解它们来自哪里和你急于给他们不正确的解释。
你可以在这里看到它:https://godbolt.org/g/8562LD
clang trunk with
-std=c++1z -Wall -Wextra -O3 -fno-implement-inlines -march=native
gcc给出了类似的结果
答案 1 :(得分:2)
我认为使用pass by reference不会复制对象
确实,它没有。
引用在堆栈上使用了多少内存
如果不需要存储,可能根本没有。
但是,除非函数是内联扩展的,否则引用参数必须在实践中存储。这是一个获取引用在内存中占用的大小的技巧:
struct test {
structWithSize_s &t;
};
size_t size = sizeof(test);
在实践中,它可能与指针完全相同。
答案 2 :(得分:0)
i
位于堆栈上的structWithSize_s t
之前。 sizeof(structWithSize_s)
是您正在衡量的,而不是sizeof(structWithSize_s &)
。
将i
移到structWithSize_s t
下方。