2014-11-07 59 views
1

如果你想在C++中复制一个对象(在堆栈上),复制大对象会慢一些吗?是瞬间复制的对象,或者是字节迭代的方式复制数据的?:较大的对象是否较慢(C++)?

class Small { 
public: 
    int stuff[32]; 
}; 

class Big { 
public: 
    int stuff[1024]; 
}; 

... 

Small small; 
Big big; 

Small small2 = Small(small); //Faster? 
Big big2 = Big(big); //Slower? 

很抱歉,但在现阶段,我没有时间来测试这一点。

回答

1

是的,较大的物体比较小的物体需要更多的时间来复制或移动。

32个整数数组需要32个操作来复制或移动。
1024个整数的数组需要1024个操作来复制或移动。

问题是时差是否显着。使用现代处理器,大多数复制操作都是纳秒级。那么,(大约)1000纳秒会影响你的程序?这取决于。如果您的程序花费毫秒或更长时间等待I/O,则差异可能不明显。

编辑1:
的空间可能更显著,时间花费复制所需的量。

大对象的一般经验法则是让他们坐下并传递指向对象的指针;避免复制或移动大型物体。指针占用的空间更小,并且比大型对象复制和移动的速度更快。还喜欢对指针的引用。

编辑2: - 堆栈
复制到堆栈取决于该处理器和该编译器的协议上。堆栈不是必需的。

在使用堆栈传递参数和局部变量分配的经典实现中,除了复制对象之外,开销还涉及递增堆栈指针变量。

所以,如果我将32个整数传递给一个函数,将会有32个复制操作加上对堆栈指针的加法操作。

通常,堆栈空间的问题更重要的是将大对象推送(复制)到堆栈所需的时间。

根据优化级别和其他属性,编译器可能能够通过指针传递对象。

+0

不会有32个整数的数组需要128个操作,1024个需要4096个操作? – name 2014-11-07 01:40:12

+0

'在使用现代处理器的情况下,大多数复制操作在复制或移动任何内容之前的时间为纳秒级,可能您仍然需要分配所需的内存,并且此操作是缓慢的,并且CPU无法执行太多了;你可以有一个超快的CPU和一个慢的'malloc',在这种情况下你会得到一个缓慢的程序。 – user2485710 2014-11-07 01:42:07

+0

@name“operation”在这里只是作为一个通用术语,我认为,不是一个具体的单位,比如时钟周期。 – 2014-11-07 01:42:12

1

需要复制的字节越多,需要的时间就越长。这对你的整体表现是否重要是另一回事。真正的杀手级是拷贝需要动态内存分配的时候。直接的字节副本通常不会太差,无论是堆栈还是堆(只要目标内存已分配)。小心将大数组放在堆栈上。

+0

除了临时值之外,我通常不使用堆栈,其余的堆栈保留在堆上 – name 2014-11-07 01:52:29

+0

@name堆栈对于局部变量很有用,如果这就是临时值,那么它比堆更快。 – 2014-11-07 01:53:15

+0

是的,我尽量保持堆分配低,并通过临时值我的意思是局部变量。 – name 2014-11-07 01:55:40

1

这并不是说较长的对象需要较长的时间进行复制,而是需要进行复制所需的处理。

是,复制

char [4096] ; 

通常需要更长的时间比复制

char [32] ; 

然而,也有可能需要更长的时间其他的事情。如果您复制构造函数并且赋值运算符执行大量其他处理,那么通常比移动数据的计算密集得多。

应对由32个整数组成的数组并不一定意味着32条指令。一些处理器有块移动指令。但是,一个块移动指令可能需要多个周期才能执行。

0

不一定,但显然更大对象意味着更多的数据需要移动,因此需要更长的时间有例为复制的开销,更重要......

如。

Big b1; 
Big b2 = b1; 

将是快速,堆到堆栈副本真快分配内存和拷贝只是一套快速的CPU指令来复制数据,通常在专用指令的优化爆裂。

Small s1; 
Small* s2 = new Small(s1); 

这可能不是那么快,你必须在相对昂贵的堆中分配内存,然后复制数据。很显然,如果Big对象真的很大,那么内存拷贝和分配会比前一个例子便宜一些。(我不能告诉你这一点是什么,它依赖于堆碎片,堆实现 - a池将更快,并执行堆栈复制所需的时间)。

然后就是这个复制构造方面,你可能在你的对象中有一个单字节数组,但是大多数对象有更多的成员变量和一个单独处理每一个的拷贝,有些甚至有特殊的例程需要执行复制,例如记录复制或锁定一些无法并行访问的共享资源。