3

1:

int a[100] = {};

2:

int a[100];
memset(a, 0, sizeof(a));

3:

int a[100];
fill(a, a + 100, 0);

上記の方法から新しい配列をゼロにする最良の方法は何ですか?それらの違いは何ですか?

4

3 に答える 3

4

1: 最高。すべての値をデフォルト値に設定します。ほとんどの場合は 0 です。

2: これは危険です。パターン 0 を配列全体にコピーします。たとえば、配列が float の場合、それがゼロとして表されるという保証はありません。また、 memset はワード単位ではなくバイト単位でコピーするため、ゼロ以外のものを渡すとあらゆる種類の問題が発生する可能性があります。たとえば、memset(a, 1, ...)で埋められ16843009ます。C 文字列を使用している場合を除き、Memset は使用しないでください。

3: 合法で読みやすい。(1) はそうではありませんが、ゼロ以外の値に簡単に拡張できます。もっと冗長ですが。

于 2013-10-11T01:49:53.897 に答える
2

VS2010、完全最適化を使用してパフォーマンスの問題を調査することにしました。

興味深い結果:

1:13105

2: 13044

3:4546

初期化なしの場合: 906.

したがって、VS2010 が case を使用するように見えますmemset1fill最適化されています。

#include "stdafx.h"
#include <Windows.h>
#include <algorithm>
#include <iostream>

int  fref()
{
    int a[1024];
    return a[512] - a[256];
}

int f1()
{
    int a[1024] = {};

    return a[512] - a[256];
}

int  f2()
{
    int a[1024];
    memset(a, 0, sizeof(a));
    return a[512] - a[256];
}



int f3()
{
    int a[1024];
    std::fill(a, a + 100, 0);
    return a[512] - a[256];
}

typedef int (*Function)();

LONGLONG time(Function function)
{
    const unsigned numLoops = 50000;
    LARGE_INTEGER start;
    QueryPerformanceCounter(&start);
    for(unsigned j = 1; j != numLoops; ++j)
    function();
    LARGE_INTEGER end;
    QueryPerformanceCounter(&end);
    return end.QuadPart-start.QuadPart;
}

Function tests[]= 
{
    &fref, &f1, &f2, &f3
};

const unsigned numTests = sizeof(tests)/sizeof(tests[0]);

LONGLONG results[numTests] = {};


int _tmain(int argc, _TCHAR* argv[])
{
    for(unsigned i = 0; i != numTests; ++i)
    {
        results[i] = time(tests[i]);
    }
    for(unsigned i = 0; i != numTests; ++i)
        std::cout << results[i] << std::endl;
    getchar();
    return 0;
}
于 2013-10-11T05:09:35.863 に答える
1

Keith のサンプル コードを使用します。GCC での違いは次のとおりです。

GCC 4.7.3: g++ -Wall -Wextra -std=c++0x -O3 -c array-fill.cpp

#include <algorithm>
#include <cstring>

int  fref() {
    int a[1024];
    return a[512] - a[256]; }

int f1() {
    int a[1024] = {};
    return a[512] - a[256]; }

int  f2() {
    int a[1024];
    std::memset(a, 0, sizeof(a));
    return a[512] - a[256]; }

int f3() {
    int a[1024];
    std::fill(a, a + 100, 0);
    return a[512] - a[256]; }

分解する

objdump -d array-fill.o | c++フィルター

00000000 <fref()>:
   0:   b8 00 10 00 00          mov    $0x1000,%eax
   5:   e8 00 00 00 00          call   a <fref()+0xa>
   a:   29 c4                   sub    %eax,%esp
   c:   8b 84 24 00 08 00 00    mov    0x800(%esp),%eax
  13:   2b 84 24 00 04 00 00    sub    0x400(%esp),%eax
  1a:   81 c4 00 10 00 00       add    $0x1000,%esp
  20:   c3                      ret
  21:   eb 0d                   jmp    30 <f1()>

00000030 <f1()>:
  30:   31 c0                   xor    %eax,%eax
  32:   c3                      ret
  33:   8d b6 00 00 00 00       lea    0x0(%esi),%esi
  39:   8d bc 27 00 00 00 00    lea    0x0(%edi,%eiz,1),%edi

00000040 <f2()>:
  40:   b8 00 10 00 00          mov    $0x1000,%eax
  45:   e8 00 00 00 00          call   4a <f2()+0xa>
  4a:   29 c4                   sub    %eax,%esp
  4c:   31 c0                   xor    %eax,%eax
  4e:   81 c4 00 10 00 00       add    $0x1000,%esp
  54:   c3                      ret
  55:   8d 74 26 00             lea    0x0(%esi,%eiz,1),%esi
  59:   8d bc 27 00 00 00 00    lea    0x0(%edi,%eiz,1),%edi

00000060 <f3()>:
  60:   b8 00 10 00 00          mov    $0x1000,%eax
  65:   e8 00 00 00 00          call   6a <f3()+0xa>
  6a:   29 c4                   sub    %eax,%esp
  6c:   89 e0                   mov    %esp,%eax
  6e:   8d 94 24 90 01 00 00    lea    0x190(%esp),%edx
  75:   c7 00 00 00 00 00       movl   $0x0,(%eax)
  7b:   83 c0 04                add    $0x4,%eax
  7e:   39 d0                   cmp    %edx,%eax
  80:   75 f3                   jne    75 <f3()+0x15>
  82:   8b 84 24 00 08 00 00    mov    0x800(%esp),%eax
  89:   2b 84 24 00 04 00 00    sub    0x400(%esp),%eax
  90:   81 c4 00 10 00 00       add    $0x1000,%esp
  96:   c3                      ret

この場合、 C スタイルの初期化 ( f1) により、確実に最適化が可能になりました。

于 2013-10-11T11:58:32.337 に答える