これが私が使っているものです:
class something
{
char flags[26][80];
} a;
std::fill(&a.flags[0][0], &a.flags[0][0] + 26 * 80, 0);
(更新:これをクラス内で使用していることを以前に明確にすべきでした。)
これが私が使っているものです:
class something
{
char flags[26][80];
} a;
std::fill(&a.flags[0][0], &a.flags[0][0] + 26 * 80, 0);
(更新:これをクラス内で使用していることを以前に明確にすべきでした。)
配列に初期化する簡単な方法0
は、次の定義にあります。
char flags[26][80] = {};
を使用したい場合std::fill
、または配列をリセットしたい場合は、これが少し良いと思います。
char flags[26][80];
std::fill( &flags[0][0], &flags[0][0] + sizeof(flags) /* / sizeof(flags[0][0]) */, 0 );
fill
配列サイズで表現すると、寸法を変更してそのままにしておくことができますfill
。これsizeof(flags[0][0])
は1
あなたの場合(sizeof(char)==1
)ですが、いつでもタイプを変更したい場合に備えて、そのままにしておくことをお勧めします。
この特定のケース(フラグの配列-整数型)では、安全性memset
が最も低い代替手段であっても、使用を検討することもできます(配列型が非ポッド型に変更されると、これは機能しなくなります)。
memset( &flags[0][0], 0, sizeof(flags) );
3つのケースすべてで、配列サイズは1回だけ入力され、コンパイラーが残りを推測することに注意してください。プログラマーエラーの余地が少なくなるため、少し安全です(1つの場所でサイズを変更し、他の場所ではサイズを忘れてください)。
編集:コードを更新しましたが、配列がプライベートであり、外部で初期化しようとしているため、コードはコンパイルされません。クラスが実際に集合体であるか(そしてそれをそのままにしておきたいか)、またはクラスにコンストラクターを追加したいかどうかに応じて、さまざまなアプローチを使用できます。
const std::size_t rows = 26;
const std::size_t cols = 80;
struct Aggregate {
char array[rows][cols];
};
class Constructor {
public:
Constructor() {
std::fill( &array[0][0], &array[rows][0], 0 ); // [1]
// memset( array, 0, sizeof(array) );
}
private:
char array[rows][cols];
};
int main() {
Aggregate a = {};
Constructor b;
}
がパブリックであることを意図している場合でもarray
、コンストラクターを使用すると、クラスのすべてのインスタンスでが適切に初期化されることが保証されるため、より良いアプローチになる可能性がありarray
ます。外部初期化は、初期値の設定を忘れないユーザーコードに依存します。
[1] @Oli Charlesworthがコメントで述べたように、定数を使用することは、複数の場所でサイズを記述(および同期を維持)する必要があるという問題に対する別の解決策です。ここでは、このアプローチをさらに異なる組み合わせで使用しました。2次元配列の外側の最初のバイトへのポインターは、2次元配列の1行先の最初の列のアドレスを要求することで取得できます。私はそれができることを示すためだけにこのアプローチを使用しましたが、それは他の人よりも優れているわけではありません&array[0][0]+(rows*cols)
を使用して多次元配列を埋める安全な方法は何
std::fill
ですか?
簡単なデフォルトの初期化は、ブレース付きの初期化を使用することです。
char flags[26][80]{};
上記は、flags
デフォルトの文字のすべての要素を初期化します。
std::fill
またはを使用した2次元配列の塗りつぶしstd::fill_n
ただし、上記を初期化するために異なる値を提供するには、十分ではありません。オプションはとstd::fill
ですstd::fill_n
。flags
(配列がpublic
クラスにあると仮定します)
std::fill(
&a.flags[0][0],
&a.flags[0][0] + sizeof(a.flags) / sizeof(a.flags[0][0]),
'0');
// or using `std::fill_n`
// std::fill_n(&a.flags[0][0], sizeof(a.flags) / sizeof(a.flags[0][0]), '1');
これを、初期化値を持つ任意のタイプの任意の2次元配列に対して一般化するために、次のようにテンプレート化された関数を提案します。sizeof
これにより、配列内の要素の合計の計算も回避されます。
#include <algorithm> // std::fill_n, std::fill
#include <cstddef> // std::size_t
template<typename Type, std::size_t M, std::size_t N>
constexpr void fill_2D_array(Type(&arr2D)[M][N], const Type val = Type{}) noexcept
{
std::fill_n(&arr2D[0][0], M * N, val);
// or using std::fill
// std::fill(&arr2D[0][0], &arr2D[0][0] + (M * N ), val);
}
今、あなたはあなたのflags
好きなものを初期化することができます
fill_2D_array(a.flags, '0'); // flags should be `public` in your class!
std::fill
またはを使用した3D配列の塗りつぶしstd::fill_n
上記のテンプレート関数にテンプレート以外のサイズパラメータをもう1つ追加すると、これを3D配列にも適用できます。
#include <algorithm> // std::fill_n
#include <cstddef> // std::size_t
template<typename Type, std::size_t M, std::size_t N, std::size_t O>
constexpr void fill_3D_array(Type(&arr3D)[M][N][O], const Type val = Type{}) noexcept
{
std::fill_n(&arr3D[0][0][0], M * N * O, val);
}
安全です。2次元配列は配列の配列です。配列は連続したストレージを占有するため、多次元のもの全体も同様になります。そうそう、それは大丈夫、安全でポータブルです。他の回答でカバーされているスタイルについて質問していないと仮定します(フラグを使用しているため、強くお勧めしますstd::vector<std::bitset<80> > myFlags(26)
)
char flags[26][80];
std::fill((char*)flags, (char*)flags + sizeof(flags)/sizeof(char), 0);
char[80]
実際の文字列型の代わりになるはずですか?その場合は、次のことをお勧めします。
std::vector<std::string> flags(26);
flags[0] = "hello";
flags[1] = "beautiful";
flags[2] = "world";
// ...
または、初期化リストをサポートするC ++コンパイラがある場合、たとえば最近のg++コンパイラは次のようになります。
std::vector<std::string> flags { "hello", "beautiful", "world" /* ... */ };