カテゴリー「C++」の10件の記事

2007年10月10日 (水)

ダミー関数呼び出しの無視できないオーバーヘッド

おはようございます。夢でわがままな男子(小学4年生)が出てきて、その子に何が良いことか悪いことかを必死になって教え続けたせいでグッタリした寝起きのカトキチです。いったい何なんだ・・・

さて、C/C++プログラムの手軽なデバッグ方法として、printf()を埋め込んでその時々の変数や状態を表示させる方法があります。

っていうか、組み込み向けで、エミュレータもなく、リモートデバッガも遅くて使えないような環境ではprintf()をコンソールに出力させる方法くらいしかないのですが・・・。

他の言語でも一般的な方法ですね。C/C++ではさらに、埋め込んだprintf()をそのまま残してリリースできるように、printf()にラッパー関数をかぶせておいて、リリース時にはその関数ごと無効化してしまう、という方法もよく行います。assert()のようなイメージですね。例えば、

(1)
#if _DEBUG
#define dbg(fmt, ...) printf("debug:" fmt, __VA_ARGS__) // __VA_ARGS__はC99の新機能
#else
#define dbg(...)
#endif

(2)
#if _DEBUG
#define dbg real_dbg
#else
#define dbg dummy_dbg
#endif

(1),(2)どちらもデバッグプリントの実現方法なんですが、(1)ではマクロでデバッグプリントを実現する方法で、無効化時にはプリプロセッサで文ごと削除する方法、(2)ではマクロの定義状況によってデバッグ用の正式な関数(real_dbg)をコールするか、ただ0を返すダミー関数(dummy_dbg)をコールするかを分ける方法です。
これによってリリース時の動作とデバッグ時の動作を切り替えられるようになります。

ところが、このうち(2)の方法には落とし穴があります。
関数呼び出しをダミー関数で削除したとしても、ダミー関数をコールすることによるオーバーヘッドが残ってしまうことです。

続きを読む "ダミー関数呼び出しの無視できないオーバーヘッド"

| | コメント (2) | トラックバック (0)

2007年1月24日 (水)

同じ内容ならマクロは何回書いても良いらしい

次のソースコードを書いたら、-Wallオプションをつけても何の文句も言われずにコンパイルしてくれました。

同じ名前のマクロは複数持てない、とだけしか考えていなかったので結構衝撃的。

続きを読む "同じ内容ならマクロは何回書いても良いらしい"

| | コメント (0) | トラックバック (0)

2007年1月22日 (月)

「g++ -c」によるオブジェクトファイルとconst修飾子の関係

「g++ -c」によってオブジェクトファイルが生成されるとき、最適化レベルによってconstを付けた変数が消えてしまうことに気づきました。

理由はまだ分からないけれど、外部ファイルから利用したいときにリンクできなくなるので注意しないといけなさそうです。

続きを読む "「g++ -c」によるオブジェクトファイルとconst修飾子の関係"

| | コメント (0) | トラックバック (0)

2007年1月10日 (水)

なぜC++には参照渡しがあるのか

仕事中、「C++の参照渡しって何であるんでしょうね」と聞かれたので、
「さあ、C++の標榜するマルチパラダイムを実現するためじゃない?」と適当に答えました。

とは言ったものの、本当かどうか不安になったので経緯を調べてみることにしました。
参考図書は、Biarne Stroustrup著の「C++の設計と進化」と「Effective C++ 原著第3版」です。

続きを読む "なぜC++には参照渡しがあるのか"

| | コメント (0) | トラックバック (0)

メンバ関数のアクセスコントロール

C++のプログラムを考えていて、ふと

  • クラスが宣言されたヘッダファイルには最小限の情報しか公開したくない(privateなどでも外部に情報を出したくない)
  • 生成したクラスのポインタからは値の取得しか出来ず、専用のAPIを呼んだ時だけ値を設定できるようにしたい

という2つの要求をどうしたら実現できるだろう、と悩みました。
値を取得できても、設定はできない(ただし特定の経路からは設定できる)というように、使用方法によってアクセスコントロールを変化させる方法です。

普通そんな状況はないでしょうが、強引に考えて、ヘッダファイルをシンプルにしておくことで、はじめてこのクラスを使用する人でも容易に使えるようにしたい場合があるかもしれません。

そこで考えたのが以下の方法。

続きを読む "メンバ関数のアクセスコントロール"

| | コメント (0) | トラックバック (0)

2007年1月 5日 (金)

C,C++でRAIIを実現する

C(GNU gcc限定),C++でRAIIを実現する方法がmemologueというブログ(http://d.hatena.ne.jp/yupo5656/)で紹介されていたので、まとめつつ転載。

RAII : Resource Acquisition Is Initialization
リソースの確保を初期化時に行うことのススメ。リソース構造を(人間にとって)分かりやすくするため、人為的なメモリリークを回避するためにも、初期化時にリソースを確保すること。
また、ユーザが明示的にリソース解放をする必要がなく、 デストラクタ内やスコープを外れたときに暗黙のうちにに解放する仕組みのことも指す。
(今は後者の方が主流の考え方らしいです)

続きを読む "C,C++でRAIIを実現する"

| | コメント (0) | トラックバック (0)

2006年10月23日 (月)

mapもどき

C++での[](大カッコ)のオーバーロードで誰もが作るだろう、mapもどきです。
(char*でもString型でもないのですが)

何の価値も無いソースですが、残しておきます。

続きを読む "mapもどき"

| | コメント (0) | トラックバック (0)

2006年7月13日 (木)

main()の3つ目の引数は

今日ももう眠いので、勉強したことだけ書きます。

CやC++でのエントリポイントとなるmain()関数は、実はコマンド引数以外にも環境変数を格納する変数を引数に持っています。

int main(int argc, char** argv, char** environ);

続きを読む "main()の3つ目の引数は"

| | コメント (0) | トラックバック (0)

2006年6月 9日 (金)

newした後のNULLチェックは無意味

Img_3400C++でクラスをインスタンス化するときに使用するnewですが、使用時には注意しなければならない点があります。

それは

「newに失敗したときは例外を返す(=NULLを返さない)」

ということです。

続きを読む "newした後のNULLチェックは無意味"

| | コメント (3) | トラックバック (0)

2006年1月18日 (水)

関数ポインタのルール(C++)

C++のメンバ関数を、他の関数へ関数ポインタとして渡すことはできません。

関数ポインタを受け取る側が、渡された関数がどのインスタンスに属するものなのか判別できないためです。インスタンスごと渡して、関数の内部でメンバ関数をコールする、といった方法を選ぶ必要があります。

ただ、これだとその関数とクラスの結びつきが強くなってしまう(関数がメンバ関数の名前をコードレベルで知っていなければならない)ので、いずれにせよあまり良い方法ではないような気がします。

(C++では確かメンバ関数名を文字列で指定できたと思ったのですが、忘れてしまいました)

続きを読む "関数ポインタのルール(C++)"

| | コメント (0) | トラックバック (0)