0

関数に渡された文字列配列のサイズを見つける方法。サイズは関数内で計算する必要があります。

#include<iostream>

using namespace std;


template <typename T,unsigned S>
unsigned arraysize(const T (&v)[S]) { return S; }

void func(string args[])
{
   unsigned m=arraysize(args);
   cout<<m;
}

int main()
{
    string str_arr[]={"hello","foo","bar"};

    func(str_arr);  
}

私が理解していないのは:

ステートメントarraysize(str_arr)がメインで使用されている場合、問題は発生しません。str_arr は配列であるため、str_arr はポインターとして機能するため、arraysize(str_arr) を使用すると、アドレスを arraysize 関数に送信していることになります (間違っている場合は訂正してください)。

しかし、関数 func() では、問題がある理由がわかりません。つまり、ステートメントarraysize(args)が文字列配列 args のアドレス (またはポインター args のアドレス) を送信します。説明?

また、上記のコードを修正してください..

4

5 に答える 5

0

関数に送信されたときに配列のサイズを決定する方法はありません。また、配列へのポインターのみが関数に送信されることも覚えておく必要があります。これにより、配列のサイズを計算することは理論的にもまったくあり得ません。

于 2013-03-06T20:09:34.917 に答える
0

ドミトリーは正しいので、もう少し説明したいと思います。これが発生する理由は、配列が C++ のファースト クラス市民ではなく、パラメーターとして渡されるとポインターに減衰し、呼び出された関数で取得するものが最初の要素へのポインターであり、サイズが失われるためです。C++ 配列を関数の引数として参照して、利用可能な代替オプションを確認できます。

于 2013-10-15T09:02:10.937 に答える
0

配列のサイズの情報は、引数に使用することを決定したときに破棄したため、関数では表示されませんstring args[]。コンパイラの観点からは、 と同じstring* argsです。関数を次のように変更できます。

template<size_t M>
void func(string (&args)[M])
{
   cout<<M;
}

でも、それはもうわかっているようですよね?

于 2013-03-06T20:11:26.700 に答える
0

ステートメントarraysize(str_arr)がメインで使用されている場合、問題は発生しません。はstr_arr配列であるためstr_arr、ポインターとして機能するため、これを使用すると、関数arraysize(str_arr)にアドレスを送信していることを意味します (間違っている場合は修正してください)。arraysize

ここで訂正しなければなりません。あなたは正しい前提を述べていますが、間違った結論を導き出しています。

重要なポイントは、実際には .xmlstr_arrの配列ですmain。配列は多くの (ほとんどの) 式コンテキストでポインターに減衰しますが、これは配列への参照が初期化される場合には当てはまりません。array_sizeこれが、が配列パラメーターへの参照を取ると宣言されている理由です。これは、配列型のパラメーターを持つ唯一の方法であり、定義された長さが付属していることを意味します。

の場合はそうではありませんfunc。関数パラメーターがプレーン配列型であると宣言されている場合、配列からポインターへの減衰がその宣言に適用されます。の宣言はfuncと同等void func(string * args)です。したがってargs、配列ではなくポインタです。func次のように呼び出すことができます

string str_non_array;
func(&str_non_array);

このため、配列への参照はそれにバインドできません。とにかく、argsそれが指している配列のサイズに関するすべての情報を完全に失いました。

arraysizeで使用されているのと同じ配列への参照トリックfuncを使用できます。

template <std::size_t N>
void func(string (&args)[N]);

しかし、これをどこでも行うのは現実的ではありません (すべての配列処理コードに単純に適用すると、コードが肥大化する可能性があります)。他の言語で使用できる長さのある配列に相当する C++ は、std::vector<string>(動的にサイズ設定された配列の場合) またはstd::array<string,N>(コンパイル時に既知の固定サイズの場合) です。後者は上記と同じコードの肥大化を引き起こす可能性があることに注意してください。そのため、ほとんどの場合、std::vector<string>さまざまな関数に渡す必要がある配列の優先型になります。

于 2013-03-06T20:25:46.517 に答える
0

str_arr文字列の配列です。するとsizeof(str_arr)、その配列のサイズが得られます。ただし、args文字列の配列のように見えますが、そうではありません。配列のように見える引数は、実際にはポインター型です。つまり、コンパイラによってstring args[]変換されます。string* argsあなたがそうするとき、sizeof(args)あなたは単にポインタのサイズを取得しています。

配列のサイズを関数に渡すか、テンプレート パラメーター サイズを使用して配列への参照を取得できます ( で行ったようにarraysize)。

template <size_t N>
void func(string (&args)[N])
{
   // ...
}
于 2013-03-06T20:11:48.790 に答える