私の知る限り、C++のvoidポインターはvoid*
何でも指すことができます。ある種の継承を使用せずにソリューションを開発したい場合、これは(私にとって)非常に役立つかもしれません。しかし、私が知りたいのは、このアプローチにパフォーマンス上の欠点があるかどうかです。
7 に答える
最大の欠点は、void ポインターを使用すると、コンパイラーが型チェックを強制できなくなることです。特にオブジェクト指向の原則をサポートする言語では、void ポインターを多用するのは奇妙だと思います。
C では、ポリモーフィックな動作を模倣するために void ポインターを見つける可能性が高くなりますが、同じタイプ セーフの問題が存在します。
には 2 つの重大なパフォーマンス上の欠点がありvoid*
ます。1 つ目は、プログラムの理解と維持がはるかに困難になることです。これは、メンテナンス プログラマーのパフォーマンスとランタイムに深刻な影響を与えます。パフォーマンスの問題があります。最速のプログラムは、最初に適切に作成されたプログラムです。これは、プログラム全体を書き直すことなく、重要な場所で局所的な最適化を行うことが可能になるためです。
パフォーマンスへの 2 番目の影響は、 が任意のvoid*
エイリアスを作成できることです。適切なエイリアシング分析は、コンパイラの最適化の重要な部分であり、これをより困難にするために何かを行うと、オプティマイザが妨げられ、コードが遅くなる可能性があります。(同様の効果があります。char*
)unsigned char*
void*
コンパイラがポイントする型について推測できないという事実以外を使用する場合、パフォーマンス上の欠点はありません。それはまだ他のようにポインタです。
void*
オブジェクトタイプへのポインタはすべてに変換できるため、Cでは任意のタイプを指すのにAが役立ちましたvoid*
。ただし、それを使ってほとんど何でもすると、未定義の動作になります。安全に元のポインタタイプにキャストバックすることしかできません。
ただし、C ++では、任意の型(テンプレート)へのポインターを格納するためのはるかに優れた方法があります。一部のテンプレート引数についてT
は、を使用できますT*
。
void*
aが他のタイプのポインターよりも大きい、またはフォーマットが異なるために、またはからのキャストがvoid*
実際の変換コードに変換されるプラットフォームがまだ存在する可能性があります。一般的な(x86、ARM)ハードウェアではそうではないため、パフォーマンスの問題はありませんvoid*
。タイプの安全性を放棄しているだけです。
はい - パフォーマンスが低下する可能性があります。を使用void *
すると、厳密なエイリアシングの仮定に基づいて最適化を無効にすることができます。
例
void fun(void * param1, int & param2)
{
param2 = 7; // 1
// do something with param1, param2 not used
param2 += 1; // 2
}
void *
変数がなかった場合、コンパイラは割り当て 1 を削除し、2 では生成するだけparam2 = 8
です。を呼び出した場合、param1
が を指している可能性があるためです。param2
fun(&i, i)
void*
何でも指すことができます。ある種の継承を使用せずにソリューションを開発したい場合、これは(私にとって)非常に役立つかもしれません
void*
何らかの関数にポインターを渡すことを考えている場合は、それがどのように使用されるかを考えてください。このオブジェクトでメソッドを呼び出したり、そのメンバーにアクセスしたりするには、とにかくそのオブジェクトの型を知る必要があります。
void*
本当に必要な場合にのみ使用してください。オブジェクトをより一般的な方法で処理する方法を探している場合は、適切な OO 設計に進んでください。ポインターを持っている場合、 「メモリ内のこのアドレスに何かがある」void*
ということしかわかりません。
ポインターを使用した場合のパフォーマンスはvoid*
、他のポインターと同じです。安全性、理解可能性、およびそれに関連するコードの拡張性と保守性は、あなたの関心事です。
他の種類のポインターではなく、void ポインターを使用するとパフォーマンスの問題が発生する理由がわかりません。私は安全性にもっと関心があります。これは、void ポインターであきらめています。