6

void*参照渡しできないのはなぜですか? コンパイラを使用すると、次のシグネチャを使用して関数を宣言できます。

static inline void FreeAndNull(void*& item)

しかし、それを呼び出そうとすると、次のエラーが発生します。

Error   1   error C2664: 'FreeAndNull' : cannot convert parameter 1 from 'uint8_t *' to 'void *&'

キャストしてもうまくいきvoid*ません

また、回避策はありますか?

4

3 に答える 3

9

答えは「はい」ですvoid*。参照によってaを渡すことができ、発生するエラーはそれとは無関係です。問題は、void*参照を受け取る関数がある場合、実際にパラメーターとしてsである変数のみを渡すことができるvoid*ということです。これには正当な理由があります。たとえば、次の関数があるとします。

void MyFunction(void*& ptr) {
    ptr = malloc(137); // Get a block of raw memory
}

int* myIntArray;
MyFunction(myIntArray); // Error- this isn't legal!

上記のコードは、示された呼び出しのために、そして正当な理由で違法です。myIntArrayに渡すことができれば、配列ではないMyFunctionタイプのバッファを指すように再割り当てされます。したがって、関数から戻ると、型の配列を指していることになり、型システムが破壊されます。これは、C ++が強い型のシステムを持っていると言っているわけではありません-そうではありません-しかし、それを破壊しようとしている場合は、明示的にいくつかのキャストを入れる必要があります。void*intint*void*

同様にこれを行うことはできません:

void MyFunction(void*& ptr) {
    ptr = malloc(137); // Get a block of raw memory
}

int* myIntArray;
MyFunction((void*)myIntArray); // Error- this isn't legal!

これができない理由についての良い参考資料として、このコードについて考えてみてください。

void OtherFunction(int& myInt) {
    myInt = 137;
}

double myDouble;
OtherFunction((int)myDouble); // Also error!

これは合法ではありません。なぜなら、doubleをとった関数にを渡そうとすると、基本的に異なるバイナリ表現を持っているため、意味のないデータでのビットを壊してしまうからです。このキャストが合法であるとすれば、このような悪いことをすることは可能でしょう。int&intdoubledouble

つまり、はい、あなたはを取り入れることができますvoid* &が、もしあなたがそうするなら、あなたは本当void*のsを渡す必要があります。Erikが上で指摘したように、解放してゼロにしたい場合は、ポインターテンプレートが最適です。

本当にこの関数にを渡したい場合はuint_8*、次のように行うことができます。

uint_8* uPtr = /* ... */
void* ptr = uPtr;
FreeAndNull(ptr);
uPtr = (uint_8*) ptr;

これには、コンパイラに「はい、これは安全ではない可能性があることはわかっていますが、とにかく実行します」と伝えるための明示的なキャストが必要です。

お役に立てれば!

于 2011-02-16T00:23:10.957 に答える
6

void * を参照で取得する場合は、uint8_t * ではなく、実際の void * を渡す必要があります。

代わりにこれを試してください:

template<typename T> inline void FreeAndNull(T * & V) { free(V); V = 0; }

編集: OP の関数名をより適切に反映し、@ 6502 の完全に正しいコメントに対処するためにサンプルを修正しました。

于 2011-02-16T00:19:53.923 に答える
1

void* へのキャストは、他の場所で説明されているよりもはるかに単純な理由で機能しません: 明示的に参照を指定しない限り、キャストは右辺値を作成します。右辺値を非 const 参照として渡すことはできません。

証明する?これを試して:

void fun(void * &) {}
int main() { int * x; void * x2 = x; fun(x); }

使用に適している場合は、これを試してください:

void fun(void * const&);

キャストが機能するだけでなく、暗黙的になりました。

参照へのキャストは危険な場合があります。実際にはコードがコンパイルされますが、その動作については説明しません。

void fun(void *&){}
int main() { int * x; fun((void*&)x); }

私の賭けは、静的キャストではなくここで reinterpret_cast を実際に行っているため、これは非常に悪いこと(tm)を行うことです。

于 2011-02-16T00:36:20.747 に答える