47

C++11 コンパイラで完全に受け入れられる次のコードを考えてみましょう。

#include <array>
#include <iostream>

auto main() -> int {
  std::array<double, 0> A;

  for(auto i : A) std::cout << i << std::endl;

  return 0;
}

標準 § 23.3.2.8 [サイズがゼロの配列] によると:

1配列は、特殊なケースのサポートを提供する必要がありN == 0ます。

2その場合N == 0begin() == end() ==一意の値。の戻り値
data()は指定されていません。

3サイズがゼロの配列に対するfront()orの呼び出しの影響は定義されていません。back()

4メンバー関数swap()には、と同等の noexcept-specification が必要 noexcept(true)です。

std::array上に示したように、 C++11 ではサイズ 0 のs が完全に許容されますint A[0];。これは、明示的に禁止されているサイズ 0 の配列 (たとえば、 .

この「矛盾」を考慮して、次の質問があります。

  • C++ 委員会がサイズ 0 のstd::arrays を許可することを決定したのはなぜですか?

  • 価値のある用途はありますか?

4

4 に答える 4

45

ジェネリック関数がある場合、その関数が特別なパラメーターでランダムに壊れると問題があります。たとえばN、ベクトルからランダムな要素を取得するテンプレート関数があるとします。

template<typename T, size_t N>
std::array<T, N> choose(const std::vector<T> &v) {
   ...
}

Nこれにより未定義の動作が発生したり、何らかの理由でゼロになった場合にコンパイラ エラーが発生したりすると、何も得られません。

生の配列の場合、制限の背後にある理由は、 を含む型が必要ないためですsizeof T == 0。これは、ポインター演算と組み合わせて奇妙な効果をもたらします。要素がゼロの配列は、特別な規則を追加しない場合、サイズがゼロになります。

しかしstd::array<>はクラスであり、クラスは常にサイズ > 0 です。したがって、これらの問題に遭遇することはありませんstd::array<>。テンプレート パラメーターの任意の制限のない一貫したインターフェイスが望ましいです。

于 2014-06-10T23:47:37.393 に答える
4

私が考えることができる 1 つの使用法は、長さゼロの配列を返すことが可能であり、具体的にチェックする必要がある機能を備えていることです。

たとえば、std::array関数のドキュメントを参照してくださいempty()。次の戻り値があります。

true if the array size is 0, false otherwise.

http://www.cplusplus.com/reference/array/array/empty/

長さ 0 の配列を返してチェックする機能は、stl 型の他の実装の標準に沿っていると思います。ベクトルとマップなので便利です。

于 2014-06-10T23:46:41.190 に答える
1

他のコンテナ クラスと同様に、オブジェクトの配列を表すオブジェクトを持つことができ、その配列を空にしたり空にしたりできると便利です。それが不可能な場合は、別のオブジェクトまたは管理クラスを作成して、その状態を正当な方法で表す必要があります。その機能がすべてのコンテナー クラスに既に含まれていると、非常に役立ちます。それを使用する際には、空の可能性があるコンテナーとして配列に関連付け、何も指していない可能性がある場合にそのメンバーを参照する前にサイズまたはインデックスを確認する習慣が必要です。

于 2014-06-11T06:47:59.850 に答える