提问人:Maxou 提问时间:6/7/2023 最后编辑:wohlstadMaxou 更新时间:6/7/2023 访问量:111
通过引用和复制调用函数的 C++
C++ call to function by reference and copy
问:
void ref(std::string& str)
{ (void)str; }
void copy(std::string str)
{ (void)str; }
int main()
{
std::string str = "Hello World";
for(size_t i = 0; i < 10000; i++)
ref(str);
}
为什么当我调用 10000 次或 .ref(str)
copy(str)
据我了解,复制一个对象应该为一个新对象分配新的空间。
如何使不重新分配此位置,并且在函数调用中仍然有一个复制对象。std::string
10000 次调用复制的 valgrind 输出
==19794== HEAP SUMMARY:
==19794== in use at exit: 0 bytes in 0 blocks
==19794== total heap usage: 1 allocs, 1 frees, 72,704 bytes allocated
为什么我没有 10000 个分配?
对 ref 的 10000 次调用的 valgrind 输出
==19794== HEAP SUMMARY:
==19794== in use at exit: 0 bytes in 0 blocks
==19794== total heap usage: 1 allocs, 1 frees, 72,704 bytes allocated
答:
3赞
KamilCuk
6/7/2023
#1
因为您的字符串足够小,可以适应小字符串优化。
3赞
Md. Faisal Habib
6/7/2023
#2
您找到的结果可能因编译器及其优化设置而异。
大多数现代编译器都在此处应用优化。
调用 copy 函数时,编译器会应用复制省略并优化对象的副本。编译器不会为复制的对象分配新的内存,而是直接重用现有对象,从而消除了额外分配的需要。std::string
std::string
从此处了解有关复制省略的更多信息
-2赞
hleme
6/7/2023
#3
在我最初的回答中,我说当子例程按值接收参数时,会进行浅层复制。@Blastfurnace在评论中提醒我,它实现了一个带有深度复制的构造函数。因此,应该进行 1000 次内存分配,并且由于编译器的内部优化,可能只发生一次内存分配。std::string
std::string
评论
1赞
user4581301
6/7/2023
std::string 是一个 32 字节的结构当然可以,但实际大小没有在任何地方指定。过去我也见过 8 字节和 40 字节。答案的其余部分读起来就像是试图回答一个不同的问题。std::string
0赞
Blastfurnace
6/7/2023
您的第一段有严重错误。传递 by 值时,将复制对象和字符串内容。否则,传递者值将允许被调用函数修改调用方的变量。只有当参数通过引用传递时,这才有可能。此外,如果传递足够长的 by 值,它将为复制的字符串内容分配内存。std::string
std::string
std::string
std::string
0赞
hleme
6/7/2023
当仅复制第一个对象且其引用的对象保持不变时,则存在浅拷贝。当复制第一个对象时,会有一个深拷贝,并且分层复制引用的对象也会被复制。您是说调用按值传递参数的子例程会进行深度复制。你错了,我只是想确认我的观点。按值将参数传递给子例程会生成浅拷贝。我使用的是带有 g++ 22.04 的 Ubuntu 11.3。
0赞
hleme
6/7/2023
@Blastfurnace,浅拷贝是C++的默认行为,但实现了深拷贝构造函数。所以因为有一个深拷贝。因此,对于 ,按值传递会分配内存。我会改变我的答案。std::string
std::string
std::string
评论
total heap usage: 1 allocs, 1 frees
- 没有 1000 个分配。str
for