Zero a pod-struct object

來源:互聯網
上載者:User

有時我們希望要將一個結構對象清零。此時我們常用的方法是調用memset。來看一下代碼

#include <cstring>struct pod_struct {#ifdef BIG_POD_STRUCT    int a[128];#else    int a;    int b;#endif};int main(){    pod_struct pod;    std::memset(&pod, 0, sizeof(pod));}

BIG_POD_STRUCT的定義在後續中會用到。我們知道,memset其實是有開銷的,對於比較小的記憶體塊,使用簡單的賦值可能更快。因為memset需要根據目標和源地址計算對齊屬性,選擇最佳的一種方案進行copy。

pod.a = 0;pod.b = 0;

這裡簡單地賦值,效率其實更高。我們來簡單做一下對比。分別使用memset和賦值的方法,迭代1000, 0000次,計算總時間。

#include <cstring>#include <clock.h>struct pod_struct {#ifdef BIG_POD_STRUCT    int a[128];#else    int a;    int b;#endif};int main(){    using namespace my_util;    const int COUNT = 10000000;    pod_struct pod;    SCOPED_CLOCK_BEGIN()    for (int i = 0; i < COUNT; ++i) {        std::memset(&pod, 0, sizeof(pod));    }    SCOPED_CLOCK_END()    SCOPED_CLOCK_BEGIN()    for (int i = 0; i < COUNT; ++i) {        pod.a = 0;        pod.b = 0;    }    SCOPED_CLOCK_END()}

這裡的scoped_clock_*宏只是用來測量時間的,實現使用clock()函數完成的,可以精確到毫秒。測量的結果是

  memset assignment
time(ms) 109 31

很顯然,用賦值的方法所用的cpu時間更短。由此我們想到能不能有什麼方法可以根據對象的大小來選擇這兩種方法呢?其實編譯器可以幫我們做這些事情。

使用一個initializer對一個pod對象進行初始化,就可以很簡單地把一個對象清零。有時我們會這麼把數組進行清零。

int a[100] = {0}; 

這裡,第一個元素初始化為0,剩餘元素自動被編譯器清零。其實更簡單的方法是,連0都不指定,直接使用一個空的初始化列表。標準規定,

If there are fewer initializers in the list than there are members in the aggregate, then each member not

explicitly initialized shall be value-initialized (8.5).

value-initialized對於內建的類型而言,就是zero-initialized,也就是簡單地清零。所以,我們可以這麼初始化pod_struct

pod_struct pod = {};

使用這個結構,編譯器會根據目標對象的大小選擇最佳的初始化方法,即使用memset或者賦值。來看一下編譯器在BIG_POD_STRUCT開啟/關閉情況下生存的彙編代碼就一目瞭然了(VC10)。

 ; BIG_POD_STRUCT not defined xor         eax,eax   mov         dword ptr [pod],eax   mov         dword ptr [ebp-8],eax

這裡編譯器把eax的值賦值給了[pod],也就是pod_struct.a,之後再賦值給了pod_struct.b。再看一下BIG_POD_STRUCT開啟後的代碼,

 ; BIG_POD_STRUCT defined push        200h   push        0   lea         eax,[pod]   push        eax   call        @ILT+440(_memset)

這裡編譯器調用了memset,而由於memset是__cdecl函數,所以參數壓棧從右至左。size=200H,value=0,dest=&pod,分別被壓棧後調用memset。200H正好是pod_struct的大小。

我測試了一下編譯器會將賦值替換為memset實現的閾值,在我的機器上是40個位元組,VC就會使用memset對pod_struct進行清零。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.