1

規格によると、5.3.4[expr.new]/7

direct-new-declaratorの式の値がゼロの場合、割り当て関数が呼び出され、要素のない配列が割り当てられます。

とで3.7.3.1[basic.stc.dynamic.allocation]/2

サイズゼロの要求として返されたポインターを逆参照する効果は定義されていません。

しかし、割り当て関数がユーザー定義であり、それが有効なポインターを返したことを知っている場合、それを逆参照することは未定義の動作でしょうか?標準では、ユーザーコードの未定義の動作を義務付けることができますか?

私が尋ねる理由は、デフォルトでは構築できないタイプのオブジェクトの動的配列を初期化するもう1つの無意味な試みです。delete[]明らかに不足していることと、それを呼び出すことしかできないこと以外に、どのような問題があり[0]ますか?私もaligned_storage正しく使用しましたか?

#include <type_traits>
#include <stdexcept>
#include <memory>
#include <iostream>

struct T {
   int val;
   T() = delete;
   T(int i) : val(i) {}
   void* operator new[](std::size_t, std::size_t cnt, const T& t)
   {
       typedef std::aligned_storage<sizeof(t),
                    std::alignment_of<T>::value>::type buf;
       T* ptr = reinterpret_cast<T*>(new buf[cnt]);
       std::uninitialized_fill_n(ptr, cnt, t);
       return ptr;
    }
};

int main()
{
    T* a = new(100, T(7)) T[0]; // using zero is legal per 5.3.4/7

    std::cout << "a[0] = " << a[0].val << '\n' // but is this legal?
              << "a[1] = " << a[1].val << '\n'
              << "a[98] = " << a[98].val << '\n'
              << "a[99] = " << a[99].val << '\n';
    delete[] a; // free the 100 aligned_storages
}

テスト実行: http: //ideone.com/iBW0z

また、MSVC ++2010EEで期待どおりにコンパイルおよび実行されます

4

2 に答える 2

3

コードに苛立たしいロジックの問題があります。

新しい式:

T* a = new(100, T(7)) T[0];

Tの削除されたデフォルトコンストラクター[expr.new]/17を呼び出します。;-(

std::vector<T>確かに今についてはよく見えます...:-)

于 2011-04-05T23:47:03.490 に答える
1

aの結果の使用の唯一の未定義の動作はreinterpret_cast、キャストが元のタイプに戻ったときです。したがって、他のすべてが正常であったとしても、すでにUBがあります。

これが本当に必要な場合は、連続したメモリの十分な大きさのブロックを割り当ててから、そのメモリに大量のメモリを配置する関数を作成してみませんnewT

于 2011-04-05T23:25:59.620 に答える