それは良いアイデアtypedefポインター?
-
09-09-2019 - |
質問
また一部のコードは、この条約のためのポインタの種類など
SomeStruct*
入
typedef SomeStruct* pSomeStruct;
あなメリットはないのか。
解決
ポインタ自体が「ブラックボックス」、つまり、その内部表現コードとは無関係でなければならないデータの一部とみなすことができるときは、適切であることができる。
基本的に、もしあなたのコードはのことはありませんのポインタデリファレンス、そしてあなただけの(時々参照することによって)API関数の周りにそれを渡し、その後、だけでなく、あなたのコードで*
sの数を減らすのtypedefん、だけでなく、ポインタが本当にとmeddledすべきではないプログラマに提案します。
これはまた、必要が生じた場合は、それが簡単に将来的にAPIを変更することができます。ポインタが最初の場所で間接参照されることになっていませんでしたので、たとえば、あなたはIDではなく、ポインタ(またはその逆)を使用して変更した場合、既存のコード中断されません。
他のヒント
ない私の経験インチ「*
」を非表示にすると読み、コードをハードになります。
私はtypedefの内部のポインタを使用するだけです。
typedef void (*SigCatcher(int, void (*)(int)))(int);
typedef void (*SigCatcher)(int);
SigCatcher old = signal(SIGINT, SIG_IGN);
そうでなければ、私が参考によりそれらをより混乱見つけます。
打撃アウト宣言は
signal()
関数へのポインタではなく、信号のキャッチャーの正しいタイプです。それは書面で(上記の修正SigCatcher
タイプを使用して)明確に行うことができます。
typedef SigCatcher (*SignalFunction)(int, SigCatcher);
あるいは、signal()
機能を宣言するには:
extern SigCatcher signal(int, SigCatcher);
つまりSignalFunction
は、2つの引数(int
とSigCatcher
)を取り、SigCatcher
を返す関数へのポインタです。そしてsignal()
自体は二つの引数(int
とSigCatcher
)を取り、SigCatcher
を返す関数です。
これを回避するためにお役にたちも送信いたします。例えば、次のコード:
int* pointer1, pointer2;
pointer2ではない int*, シンプル int.がtypedefsいえば:
typedef int* pInt;
pInt pointer1, pointer2;
両方とも int* ます。
私の答えは"No"です。
なぜですか?
でも、まずは、単に単一の文字交換 *
他の単一文字 p
.ることが ゼロ します。それだけではいるのだからこそ、常に悪いの余分なものが意味を成さない。
第二に、そして、その重要な理由 の *
において意味を持つことがない隠.場していただくためにも、このような機能
void foo(SomeType bar);
void baz() {
SomeType myBar = getSomeType();
foo(myBar);
}
私は期待しないことを意味 myBar
変化することにより渡す foo()
.やっぱり通過による価値ので、 foo()
み見のコピー myBar
でしょ?ない場合 SomeType
はつまり、別名を意味のポインタを!
このことCのポインタはC++のスマートポイント:だという事実を隠すようにポインタ利用は、混乱が生じることが全く不要です。くださいなエイリアスのおのポインタ.
(私の癖typedefingポインタの種類は間違った方向に誘導されたように多くの星の一つはプログラマーとして http://wiki.c2.com/?ThreeStarProgrammer .)
これはスタイルの問題です。あなたは、Windowsのヘッダファイルで非常に頻繁にこの種のコードを参照してください。彼らは代わりに小文字のpを前に置くのすべて大文字のバージョンを好む傾向にあるものの。
個人的に私はtypedefでのこの使用を避けます。これは、明示的に、彼らはPFooよりはFoo *ほしいと言うのユーザーを持つことが非常に明確です。 typedefのが最善のSTLは、読みやすくするために、これらの日適しています)。
typedef stl::map<stl::wstring,CAdapt<CComPtr<IFoo>> NameToFooMap;
これは(非常に多くの回答など)によって異なります。
あなたは、オブジェクトがポインタであることを偽装しようとしているとして、Cで、これは非常に一般的です。あなたは、これはすべての機能が、(我々はそれが下にポインタである知っているが、それはあなたが操作しているオブジェクトを表します)操作するオブジェクトであることを暗示しようとしている。
MYDB db = MYDBcreateDB("Plop://djdjdjjdjd");
MYDBDoSomthingWithDB(db,5,6,7);
CallLocalFuc(db); // if db is not a pointer things could be complicated.
MYDBdestroyDB(db);
MYDBの下側には、おそらくいくつかのオブジェクトのポインタです。
C ++ではこれはもはや必要とされない。
我々は、参照することによって物事を周りに渡すことができますし、メソッドは、クラスの宣言に組み込まれている主な理由ます。
MyDB db("Plop://djdjdjjdjd");
db.DoSomthingWithDB(5,6,7);
CallLocalFuc(db); // This time we can call be reference.
db.destroyDB(); // Or let the destructor handle it.
typedefのは、コードを読みやすくするために使用されるが、typedefでは混乱を増加させるようにポインタを作っています。 typedefポインタを避けるために、より良います。
のディスカッション登板関心の言語が考慮されていないC ++のためのC.波及効果であると仮定すると。の
タグなしの構造体へのポインタのtypedefを使用して
(構造のためtypedef
を使用して、興味深いサイドライトを上げるのポインタとして定義される構造体の質問のサイズ)ポインタます。
タグなしコンクリートを考える(不透明ではない)構造型定義
typedef struct { int field1; double field2; } *Information;
メンバーの詳細は、この議論に完全に接線方向です。すべての重要なことはtypedef struct tag *tag;
のように、このない不透明なタイプは(そしてあなたがタグなしでtypedef
を経由して、このような不透明なタイプを定義することはできません)ということです。
提起質問は、「どのようにあなたがその構造体のサイズを見つけることができる」とは?
短い答えが「唯一の型の変数を経由して」です。 sizeof(struct tag)
で使用するいかなるタグはありません。あなたは有効たとえば、 を書くことはできない、とsizeof(*Information)
sizeof(Information *)
はポインタ型へのポインタのサイズではなく、構造型のサイズです。
実際には、あなたはダイナミックアロケーション(または動的な割り当てを模倣代理技術)を経由して除くものを作成することはできません。ポインタInformation
と呼ばれている構造型のローカル変数を作成する方法はありません、また(グローバルまたはstatic
)構造型の変数、ファイルスコープを作成する方法があり、また、このような構造を埋め込む方法があります別の構造体または共用型に(例えば、構造体へのポインタとは対照的に)。
あなたはできる - 書き込み - 必要があります:
Information info = malloc(sizeof(*info));
別にポインタがtypedef
に隠されているという事実から、これは良い習慣です - info
の変化のタイプならば、サイズの割り当てが正確なままになります。しかし、この場合には、それはまた、構造体のサイズを取得するために、構造を割り当てることが唯一の方法です。そして、構造体のインスタンスを作成するための他の方法はありません。
これは危険ですか?
これは、あなたの目標によって異なります。
これは、不透明なタイプではない - ポインタ型をtypedef
'dされたときに構造の詳細が定義されなければならない
これは、動的なメモリ割り当てとともに使用することができるタイプである。
これは、無名のあるタイプです。構造型へのポインタには名前がありますが、構造タイプ自体にはありません。
あなたが動的割り当てを強制したい場合は、、これはそれを行うための方法のようです。
全体的に、しかし、それは悟りより混乱と不安を引き起こす可能性が高くなります。
概要
タグなしstucture型へのポインタを定義するためにtypedef
を使用して、一般的には、悪い考えです。
list<const pSomeStruct> structs;
として
list<SomeStruct * const> structs;
要素が割り当て可能でないので、法的STLコンテナではない。
この質問を参照してください。
はありません。
それは悲惨なあなたがconst
とそれを混ぜた瞬間を、あなたの人生を行います。
typedef foo *fooptr;
const fooptr bar1;
const foo *bar2
bar1
と同じタイプをbar2
していますか?
そして、ええ、私はハーブサッターの達人を引用しています。多くの真実彼女は話しました。 ;)
- 編集 -
に引用記事へのリンクを追加します。
http://www.drdobbs.com/conversationsa-midsummer-nights -madness / 184403835 の
のWin32 APIは、ほぼすべての構造(すべてではない)でこれを行います。
POINT => *LPPOINT
WNDCLASSEX => *LPWNDCLASSEX
RECT => *LPRECT
PRINT_INFO_2 => *LPPRINT_INFO_2
それは一貫しているどのようにそれはうれしいですが、私の意見ではそれはどんな優雅さを追加しません。
のtypedefでの目的は、実装の詳細を非表示にすることですが、typedefの-INGのポインタプロパティは、あまりにも多くを隠し、理解/読みコードが難しくなります。 だから、それをしないでください。
<時間> あなたが(頻繁に行うには良いことです)実装の詳細を非表示にする場合は、、ポインタの一部を非表示にしないでください。標準FILE
インターフェイスのプロトタイプで、たとえば乗ります:
FILE *fopen(const char *filename, const char *mode);
char *fgets(char *s, int size, FILE *stream);
ここでfopenを返します。のポインタの(あなたのために実装の詳細を知らない)いくつかの構造FILE
へ。この場合には、それはそれがポインタであるという事実を隠したいくつかのPFILEタイプで働いている可能性があるため、たぶんFILE
は、このような良い例ではありません。
pFILE fopen(const char *filename, const char *mode);
char *fgets(char *s, int size, pFILE stream);
しかし、それだけで直接に指摘された内容の周りにあなたは決して混乱ために働くだろう。あなたはいくつかの場所は、コードを変更するいくつかのポインタをtypedefの瞬間は私の経験で読み取ることが非常に困難になります。
いくつかの時間前、私はこの質問に「いいえ」と答えていると思います。今、スマートポインタの上昇に伴って、ポインタは常にもうスター「*」で定義されていません。だから、ポインタまたはないというタイプについての明白なものは何もありません。
だから今、私は言うだろう:それはそれは、「ポインタ型」であることを非常に明確にされているとして、限り、ポインタをtypedefのために罰金です。それはあなたがそれのために特別に接頭辞/接尾辞を使用しなければならないことを意味します。いいえ、「p」は、たとえば、十分な接頭辞ではありません。私はおそらく "PTR" で行くと思います。