#author("2022-12-12T00:27:16+09:00","","") #author("2022-12-12T00:44:41+09:00","","") #topicpath ////////////////////////////////////////////////////////////////////////////// * 目次 [#e158d013] #contents(); ////////////////////////////////////////////////////////////////////////////// * 下位ページ [#r5d24f18] #ls2(Lang/C++/); ////////////////////////////////////////////////////////////////////////////// * C++ のキーワード [#u4a91d35] - TR1 - スマートポインタ - [[Boost>http://www.boost.org/]] -- [[Boost C++ Libraries>http://boost.cppll.jp/HEAD/]] -- [[Let's boost>http://www.kmonos.net/alang/boost/]] ////////////////////////////////////////////////////////////////////////////// * プリプロセッサ [#k54e3482] ** #error <error-message> [#u2b926b8] - プリプロセッサ実行時、そこを通ると<error-message>を出力して処理を停止する。 - 書式: #error "error-message" ////////////////////////////////////////////////////////////////////////////// * 初期化 [#xe60f555] - コンストラクタでの初期値代入ではなく、「初期値で生成」する。 class CTest { public: CTest(); ~CTest(); ・・・ private: CInfo m_info; int m_id; }; CTest::CTest() :CInfo( 0 ), // 初期値で生成するため、メンバ変数のコンストラクタをここで呼ぶ m_id( 0 ) { // メンバ変数への初期値代入をここに記述しない } //////////////////////////////////////////////////////////////////////////////// * 継承される可能性のあるclassは、デストラクタを仮想にする [#fc01395d] - これは下記のような問題を回避する為。 ++ 継承した子クラスを作る ++ その子クラスが、親クラスの型で自分のインスタンスのポインタを返すような使い方をされる場合がある。 ++ このとき、その親クラスのポインタに対して delete をしてしまうと、子クラスの部分だけがdeleteされていない、中抜けのおかしな実体になってしまう。 ++ その中抜けなインスタンスに対してアクセスすると、そのときの動作が未定義になってしまう。 ////////////////////////////////////////////////////////////////////////////// * 型の別名宣言 using [#kbf8ccce] //============================================================================ ** 型を別名宣言する場合 [#q46e5948] - 従来は typedef で型の別名宣言が出来たが、C++ においては、 using で行う方法もある typedef <元の型名> <新しい型名>; // 従来の宣言形式 using <新しい型名> = <元の型名>; // using を使用した宣言 //============================================================================ ** 関数ポインタに対して宣言する場合 [#gd03dcaf] typedef void (*funcptr)(int); // typedef を使用する場合 using funcptr = void (*)(int); // using を使用する場合 - see also: [[std::function>Lang/C++/C++11#std-function]] ////////////////////////////////////////////////////////////////////////////// * コンパイル時に構造体のサイズを知る [#pb839232] - 下記のようなマクロを仕込むことで、コンパイル時に構造体 foo のサイズが取得出来る。 #define PRINT_SIZEOF(type) PRINT_SIZEOF_(type, __LINE__) #define PRINT_SIZEOF_(type, line) \ void print_sizeof_##line() { asm volatile("size of " #type " is %0" :: "g"(sizeof(type))); } struct foo { type variable; }; PRINT_SIZEOF(struct foo) - これを実行するとエラーが発生し、その際に構造体サイズがコンパイルログとして出力される。 ////////////////////////////////////////////////////////////////////////////// * cast [#qa1343fa] - c++ の cast には4種類がある。 //============================================================================ ** static_cast [#static_cast] - 静的キャスト - 比較的安全な型変換に使用する。使用する場面は下記: -- 整数型間や、ポインタ型間 -- 列挙型(enum)と整数型間 -- const / volatile の付加 -- オブジェクトポインタと void ポインタとの変換 -- アップキャスト(class 型ポインタからその基底 class のポインタを取り出す) -- ダウンキャスト(class 型ポインタからその派生 class のポインタを取り出す) -- 変換コンストラクタによる変換 -- 型変換演算子による変換 -- 仮想基底クラスを含まない継承関係に於ける基底クラスと派生クラスの相互の変換 - 例 short s = 0xf5; int i = static_cast<int>(s); //============================================================================ ** dynamic_cast [#dynamic_cast] - 動的キャスト - 使用する場面は下記: -- ダウンキャスト(class 型ポインタからその派生 class のポインタを取り出す) -- クロスキャスト(或る class 型の基底 class から、別の基底 class へのポインタを取得) - ポインタ型への変換で失敗すると、結果が nullptr となる。 - 参照型への変換で失敗すると、bad_cast 例外が送出される。 - 例 class base_t { public: base_t() {} virtual ~base_t() {} ... }; class child_t : public base_t { public: ... void set_a( int a ) { m_a = a; } private: int m_a; }; child_t* cx = new child_t; base_t* bx = dynamic_cast<base_t*>(cx); // Up cast child_t* cy = dynamic_cast<child_t*>(bx); // Down cast //============================================================================ ** const_cast [#const_cast] - const キャスト - 変換元の型から const 装飾子や volatile 装飾子を除去する為に用いる。 - const 修飾子を取り除くこと(=元々変更出来ない筈のオブジェクトが変更される可能性が生じる)や、volatile 修飾子を取り除くこと(=アクセスすべきオブジェクトにアクセスが行われなくなる可能性が生じる)は好ましくない為、他に方法がない場合以外では使用しないことが望ましい。 //============================================================================ ** reinterpret_cast [#reinterpret_cast] - 再解釈キャスト - 使用場面 -- 互換性のないポインタ型同士の変換 -- 整数型とポインタ型との間の変換 - このキャストを用いて「ポインタ型→整数型(但し、桁溢れを起こさない型であること)→元のポインタ型」な変換を行った場合、最後のポインタ型は最初のポインタ型と同一の値であることが保証される。 - 下記の制限事項がある: -- cv 修飾の削除は出来ない -- メンバポインタと非メンバポインタ間の変換は出来ない -- メンバ変数へのポインタとメンバ関数へのポインタ間の変換は出来ない -- メンバ関数のポインタと非メンバ関数へのポインタの変更は出来ない ////////////////////////////////////////////////////////////////////////////// * new / delete [#new-delete] //============================================================================ ** new [#new] - 動的なメモリ確保を行う - 例 int* p = new int; // int 型変数を動的にメモリ確保 int* p = new int[100]; // int 型配列(要素数:100)のメモリを動的に確保 int* p = new(nothrow) int; // int 型変数を動的にメモリ確保。但し確保出来なかった場合に例外送出ではなく nullptr を返す //============================================================================ ** delete [#delete] - new で確保された領域の開放を行う - 例 delete p; // 配列でないメモリ領域を開放 delete[] p; // 配列として確保されたメモリ領域を開放 //============================================================================ ** 配置 new [#placement-new] - 既に存在している領域に class のメモリ領域を割り当てる - 例 class ClsAA { private: int a; char b[10]; } size_t mem_size = sizeof(ClsAA); // 確保するメモリ領域サイズ void* p = new unsigned char[mem_size]; // メモリ領域の確保 ClsAA* a = new(p) ClsAA; // 確保したメモリ領域に ClsAA 型の class のメモリ領域として割り当てる ////////////////////////////////////////////////////////////////////////////// * アライメント [#alignment] //============================================================================ ** アライメントの取得 [#alignof] - 書式: alignof(型); //============================================================================ ** アライメントの指定 [#alignas] - 書式: alignas(定式名); alignas(型名); - 以下では alignas は使用出来ない: -- ビットフィールド -- 関数の仮引数 -- catch 構文の仮引数 - 使用例 class ClsAA { private: alignas(uint32_t) uint8_t m_a; alignas(uint32_t) uint16_t m_b; alignas(uint32_t) uint32_t m_c; }; //============================================================================ ** そもそも、アライメントとは? [#f4e4e75f] - アライメントは、オブジェクトのための領域をメモリ上に配置する際のアドレスの境界位置のこと。 - 例えば int のサイズが 4 byte の環境では、アライメントは 4 の倍数となり、 4 の倍数のアドレスに配置することで int 型変数の領域に高速にアクセス出来るようになる場合がある。 - CPU によっては、アライメントに合わない位置に配置されたオブジェクトにはアクセスできない場合がある。 - それぞれの型のオブジェクトは、alignof() で返された値の倍数となるアドレスに配置する必要がある。 ////////////////////////////////////////////////////////////////////////////// * gcc / g++ [#f33f7483] - gcc (g++) で std ライブラリを使用したコードを make する際、libstdc++.a が必要になる LDFLAGS += -lstdc++ ////////////////////////////////////////////////////////////////////////////// * 参考リンク [#v3be8bd5] - [[Bjarne Stroustrup Interview about C++>http://hp.vector.co.jp/authors/VA000092/jokes/strup.html]]