3

私は、呼び出し元がポインターの配列と配列の長さを渡す API を使用しています。arg[0]コードをより読みやすく/保守しやすくするために、各引数を 、arg[1]などで参照するのではなく、効果的に名前を付けられるようにしたいと考えています。渡された配列は、オプションの引数のために異なるサイズになる可能性がありますか?

私はこのようなことをしようとしています:

void myFunc(int out_args[], size_t nargs) {
  int &foo = out_args[0];
  int &bar = out_args[1];    // bar is optional argument. is this safe?
  ...
  foo = 5;
  if(2 >= nargs)
    bar = 10;
  ...
}

引数は出力引数であるため、それらへの参照が本当に必要であることに注意してください。では、実際に使用したことがない場合、args[1] へのダングリングっぽい参照を使用しても安全ですか?

&参照を実装する方法は、参照の変数宣言で として扱うことであり* const、参照を使用するたびに、コンパイラが自動的にポインターを逆参照するため、これは安全だと思います。つまり、ボンネットの下では、私が書いたものが次のようなものに翻訳されると想像しています

void myFunc(int out_args[], size_t nargs) {
  int *const foo = &out_args[0];
  int *const bar = &out_args[1];    // bar is optional argument. is this safe?
  ...
  *foo = 5;
  if(2 >= nargs)
    *bar = 10;
  ...
}

この場合、コードが実際にアクセスしてはならないメモリにアクセスすることは決してないと私は信じています。したがって、上記のバージョンがこれと同等であれば、問題ないはずですよね?


編集:私は基本的にプラグインを書いています。私が使用していて何もできないAPIは、次のようなもので私のコードを呼び出すことができます

int ret_vals[1];     // only care about 1 return value
myFunc(ret_vals, 1);

また

int ret_vals[2];     // care about both return values
myFunc(ret_vals, 2);

あるいは

myFunc(NULL, 0);     // ignore all return values; just marvel at the side effects

私のコードはすべての場合に機能する必要があります。

4

2 に答える 2

3

少なくとも 2 つの要素からなる配列の最初の要素へのポインターでないargs[1]場合に式を評価するのは、未定義の動作です。argsのようにすぐにアドレスを取得することは、少なくとも 1 つの要素からなる配列の最初の要素を指している&args[1]場合にのみ有効です。args

基本的には行いません。

于 2013-10-23T23:32:25.390 に答える
1

では、実際に使用したことがない場合、args[1] へのダングリングっぽい参照を使用しても安全ですか?

標準は、§ 8.3.2 で参照が有効なオブジェクトにバインドされることを課しています。

参照への参照、参照の配列、および参照へのポインタがあってはなりません。[...] 参照は、有効なオブジェクトまたは関数を参照するように初期化されます。[ 注: 特に、null 参照は明確に定義されたプログラムには存在できません。そのような参照を作成する唯一の方法は、null ポインターを逆参照することによって取得された「オブジェクト」にバインドすることであり、未定義の動作を引き起こすからです。[...] — 終わりの注記]

安全ではないということです。

参照の実装方法は、参照の変数宣言で & を * const として扱うことであり、参照を使用するたびに、コンパイラが自動的にポインターを逆参照するため、これは安全だと思います。

いいえ、そうしないでください。繰り返しますが、標準では参照の実装方法を指定していません。実際、§ 8.3.2 では次のように述べられています。

参照がストレージを必要とするかどうかは指定されていません。

コードに関しては、パラメーターが存在することを確認したら、パラメーターに名前を付けることができます。

void myFunc(int out_args[], size_t nargs) {
  int &foo = out_args[0];
  ...
  foo = 5;
  if(nargs >= 2) {
    int &bar = out_args[1];
    bar = 10;
  }
  ...
}

C++ での C スタイルの配列の使用は推奨されていないことに注意してください。通常は、代わりにstd::vectororを使用することをお勧めします。std::array

于 2013-10-24T01:43:03.803 に答える