#include <vector>
typedef std::vector<char> vc;
typedef std::vector<vc> vvc;
vvc f() {
const int N = (1 << 15);
return vvc(N, vc(N)); // 1 GB
}
int main () {
vvc v;
v = f();
while(true); // Why 2GB allocated ?
return 0;
}
用clang -O2和g ++ -O2编译。同样的行为。
编辑:在一些答案中有多种方法可以修复此代码。 但我的观点是要理解这段代码。当然有一个临时对象,但它应该在分号处消失,并且应该将1GB的内存返回给系统。这个问题打算问为什么它不会发生。
编辑2:临时对象的析构函数确实在分号之前调用。
答案 0 :(得分:4)
您的代码中的作业我们有充分的理由徒劳地宣传; - )
如果您使用了初始化,那么允许进行RVO优化,并且正如其他实验一样,它实际上似乎也在起作用。
使用赋值函数返回一个对象,然后必须将其复制到目标,然后才能对临时文件进行核对。虽然数据流肛门可能会被优化,但这是一个难以捕捉并被认为难得使用的案例。因此,您将在所有其他方面受到性能损失。
编辑:要看到临时确实在适当的时候点,我建议使用调试器和单步执行功能。或者看看assy上市。对于抽象机器,dtor调用必须在下一条指令之前发生。
然而,优化的代码更自由地使用'as''规则。如果代码无法区分它,它可能会推迟一点,你可能会体验到这种效果。
C ++ 11注意:在C ++ 11中,向量获得了另一个从rvalue移动的op =。这样可以解决这个特殊情况,但是需要时间才能让所有编译器缩小差距,特别是所有类都能获得移动的东西。寻找移动的前11代码将使用swap()代替=。
答案 1 :(得分:4)
我的猜测是,您正在查看操作系统显示分配给进程的内存量,以及您的编译器还不支持C ++ 11的移动分配。< / p>
因此会发生以下情况:
因此,结果是操作系统为您的进程分配2GB,其中1GB分配给向量,1GB可用于将来在您的程序中分配(但不能用于另一个进程中的分配)。
答案 2 :(得分:2)
我刚刚在win32,vc7上测试过。
您的代码分配2Gb。如果改为:
int main () {
vvc v = f();
while(true);
它只需要1Gb。
我想原因 - 是矢量之间的复制操作。
v = f()
- 调用构造函数。您的情况 - 默认c&tor;并复制(运算符=
)到空对象。应对需要2 Gb。
f()
(创建向量和返回)的内部操作可以使用RVO,并且没有任何应对和额外分配。
答案 3 :(得分:1)
编辑:有多种方法可以修复这些代码中指向的代码 答案。但我的观点是要理解这段代码。当然有一个 临时对象,但它应该在分号和1GB的时候消失 内存应该返回给系统。这个问题打算问 为什么没有发生。
在Windows上,我用gcc编译你的测试并运行。我发现Private Bytes
的值在程序启动后会增加,然后开始减少然后最终停止变化。所以在这个操作系统内存返回系统。顺便说一下,我使用Process Explorer
来获取有关Private Bytes
的信息。
我假设您在Linux上进行了测试,并且此操作系统内存未返回给系统。如果它没有被使用,如果我是对的话,它最终被移动到寻呼区域。
答案 4 :(得分:0)
我认为会复制返回值。比暂时的2个vvc副本存在。 每个都有2 ^ 30个字符(= 1GB)
据我所知,允许编译器但不需要删除复制操作
我找到了这个链接 http://en.wikipedia.org/wiki/Return_value_optimization