1

これは一種の疑似コードですが、私が知りたいことを明確にする必要があります。3 つのバリアントすべてが異なるコードで表示されます。

私の質問は、これを行う正しい方法とその理由です。(コード スニペットのコメントも参照してください)

test.h 最初の方法:

class Test {
    public:
        Test() 
            :_buffer(NULL)
         {
            _buffer = new char[1024];
        }

        ~Test() {
           delete _buffer;
        }

        int Function() {
           //use some function like inet_ntop doesn't work _buffer is not filled
           inet_ntop(p->ai_family, addr, _buffer,  sizeof(_buffer)-1);
           //here sizeof(_buffer) returns 4, WHY ?
           cout << sizeof(_buffer) << endl;
        }

    private:
        char *_buffer;
};

test.h 2 番目の方法:

class Test {
    public:
        Test() {
            //_buffer is never initialized WHY ?
        }
        ~Test() {
           //_buffer is never deleted WHY ?
        }
        int Function() {
           //use some function like inet_ntop works correctly here _buffer is filled 
           inet_ntop(p->ai_family, addr, _buffer,  sizeof(_buffer)-1);
           //here sizeof(_buffer) returns 1024, WHY ?
           cout << sizeof(_buffer) << endl;
        }
     private:
         char _buffer[1024];
};

test.h 3 番目の方法:

class Test {
    public:
        Test() {
        }
        ~Test() {
        }
        int Function() {
           char buffer[1024];
           //use some function like inet_ntop works correctly here _buffer is filled
           inet_ntop(p->ai_family, addr, _buffer,  sizeof(_buffer)-1);
           //here sizeof(_buffer) returns 1024
           cout << sizeof(_buffer) << endl;
        }
     private:
};
4

3 に答える 3

6

C++クラスでchar配列を宣言する正しい方法は何ですか?

ない。
C++ では、次を使用するのが正しい方法です。

std::string buffer;

これがまさに C++ が提供する理由ですstd::string。以下から解放されます。

  • #1&のようにメモリを明示的に管理する
  • のように、静的に割り当てられた配列の境界を上書きします#2

あなたが示す3つの例は同等ではないことに注意してください。
#1&#2文字バッファーの有効期間をオブジェクト インスタンスにバインドしますが、
Wh​​ile#3は同じことをしません。

CスタイルのAPIに渡すためだけにローカルバッファ(サイズは固定)が必要な場合、その使用法はによって提供されるグッズをうまく利用できずstd::string、おそらく静的に割り当てられた文字配列がはるかに適していることに注意してください。

あなたの要件がのようである場合#1#2より良いオプションは ofcoursestd::stringです。

于 2013-01-13T07:53:46.693 に答える
2

最初のバリアント: 文字配列はヒープから割り当てられます。IIRC、デストラクタでの削除はdelete [] _buffer.

2 番目のバリアント: 文字配列はクラスの一部であり、クラスと共に生死を分けます。クラスのインスタンス化方法に応じて、ヒープまたはスタックから割り当てることができます。

3 番目のバリアント: 文字配列はスタックに割り当てられ、外側のスコープ (この場合はFunction()—) が終了すると解放されます。

そうは言っても、正当な理由で文字の配列が本当に必要でない限り、を使用するstd::string方がはるかに優れています。

于 2013-01-13T07:57:42.327 に答える
2

あなたがやろうとしていることに「唯一の真の方法」があるとは思いません。それぞれの方法にはトレードオフがあります。具体的には:

方法 1) ヒープにメモリを割り当てます。(わずかな) パフォーマンスの低下が発生します。ただし、メモリ内のクラスのサイズは縮小されます。クラスをスタックに割り当てると、この方法で無駄になるスタック スペースが少なくなります。delete []他の人が述べたように、ステートメントを使用する必要があります。

あなたのコメントに関して、 buffer は char ポインターであるため、 sizeof(buffer) は 4 を返します。プラットフォームでは、ポインターが 4 バイトの大きさになるように定義されています。sizeof は記述された型で機能するため、割り当てられた配列のサイズは報告されません。inet_ntop は、バッファーのサイズが 4 バイトしかないことを伝えているため、バッファーをいっぱいにしません。inet_ntop は、そのバッファーが小さすぎるため、単純に失敗します。

方法 2) これは、方法 1 の余分なヒープ割り当てと引き換えに、クラス サイズを増やします。

コメントに関しては、C++ が処理するため、バッファーは初期化または削除されません。サイズが 1024 バイトの char 配列を提供するようにコンパイラーに指示したため、1 つ提供されます。コンパイラの初期化/クリーンアップは必要ありません。また、型が 1024 バイトの char 配列であるため、sizeof は 1024 を返します。したがって、コンパイラはこれを認識し、配列サイズを提供します。ポインターを要求しなかったため、ここではポインターのサイズを返しません。

方法 3) この方法は、代わりに関数が呼び出されるたびにバッファーを割り当て、それをスタックに置きます。データの処理方法によっては、これが最適なソリューションである場合もあれば、まったく適用できない場合もあります。関数の終了後にバッファーが必要ない場合は、それが適切な選択です。

于 2013-01-13T08:13:15.567 に答える