関数のオーバーロードのためだけにC ++コンパイラを使用するのは悪い習慣ですか?


60

そのため、特定のプロセッサでCを使用したソフトウェア設計に取り組んでいます。ツールキットには、CおよびC ++をコンパイルする機能が含まれています。私がやっていることに関しては、この環境で利用可能な動的メモリ割り当てはなく、プログラムは全体的にかなり単純です。言うまでもなく、このデバイスにはプロセッサー能力やリソースがほとんどありません。C ++を使用する必要はまったくありません。

そうは言っても、関数のオーバーロードを行う場所はいくつかあります(C ++の機能)。いくつかの異なるタイプのデータを送信する必要がありますが、printf何らかの%s(またはなんらかの)引数でスタイルの書式設定を使用する気はありません。私はC ++コンパイラにアクセスできない人を何人か見ましたprintfが、私の場合はC ++サポートが利用可能です。

これで、なぜ関数をオーバーロードする必要があるのか​​という疑問を最初から得ることができると確信しています。だから私は今すぐそれに答えようとします。シリアルポートからさまざまな種類のデータを送信する必要があるため、次のデータ型を送信するオーバーロードがいくつかあります。

unsigned char*
const char*
unsigned char
const char

私は、これらすべてを処理する1つのメソッドを持たないことを好みます。私はちょうどそれがシリアルポートを送信する関数を呼び出すときに、私は多くの資源を持っていないので、私はかろうじて行うにはしたくない何でもいいけど、私の送信を。

他の人が私のプログラムを見て、「なぜCPPファイルを使用しているのですか?」だから、それが私の唯一の理由です。それは悪い習慣ですか?

更新

私は尋ねられたいくつかの質問に対処したいと思います:

あなたのジレンマに対する客観的な答えは以下に依存します:

  1. C ++を使用する場合、実行可能ファイルのサイズが大幅に増加するかどうか。

現在、実行可能ファイルのサイズは、プログラムメモリの4.0%(5248バイトのうち)とデータメモリの8.3%(342バイトのうち)を消費しています。つまり、C ++用にコンパイルしています... Cコンパイラを使用していないため、Cでどのように見えるかわかりません。私はこのプログラムがこれ以上成長しないことを知っているので、リソースがどれだけ限られているかについては、私はそこで大丈夫だと言います...

  1. C ++を使用している場合、パフォーマンスに顕著な悪影響があるかどうか。

ある場合、私は何にも気づいていません...しかし、それでも私は完全に理解していないので、私はこの質問をしている理由かもしれません。

  1. Cコンパイラーのみが使用可能な別のプラットフォームでコードを再利用できるかどうか。

私はこれに対する答えが間違いなくノーであることを知っています。別のプロセッサへの移行を実際に検討していますが、より強力なARMベースのプロセッサのみです(事実、C ++コンパイラツールチェーンを持っていることは事実です)。


59
//コメントができるように、C機能のみを使用するプロジェクトにC ++を使用することが知られています。それが機能する場合、どうしてですか?
ジュール

76
悪い習慣は、Cが提供していない機能をうまく使用している場合、Cに自分自身を制限することです。
ジェリー

35
「C ++コンパイラを使用する」と言うときは、「C ++を使用する」という意味です。言うだけです。C ++コンパイラでCをコンパイルすることはできません、CからC ++に簡単に切り替えることができます。これは実際に行うことです。
user253751

4
「私がやっていることについては、プロセッサに動的なメモリ割り当てはなく、プログラムは全体的にかなり単純です。デバイスにはプロセッサのパワーやリソースがほとんどないことは言うまでもありません。C++を使用する必要はまったくありません。」これらの2つの文の最初の文がC ++を使用しない理由であると思われます。C++を使用するのはかなり悪いためです。C ++は組み込みシステムで使用するのにまったく問題ありません。
ファラプ

21
@Julesあなたはこれを知っていて、しばらく考えていたと確信していますが、誰かがこれを読んでいない場合://コメントはC99以来C標準にありました。
デイビスラー

回答:


77

私はそれをそれ自体「悪い習慣」と呼ぶことはしませんが、それが本当にあなたの問題の正しい解決策だと確信しているわけでもありません。4つのデータ型を処理するための4つの別個の関数だけが必要な場合、Cプログラマーが太古からやってきたことを実行しないでください。

void transmit_uchar_buffer(unsigned char *buffer);
void transmit_char_buffer(char *buffer);
void transmit_uchar(unsigned char c);
void transmit_char(char c);

とにかく、C ++コンパイラが舞台裏で実際に行っていることであり、プログラマにとってそれほど大きなオーバーヘッドではありません。「なぜC ++コンパイラーで非Cを書いているのか」という問題をすべて回避し、プロジェクトの他の誰もC ++のどの部分が「許可」され、どの部分が許可されないのか混乱しないことを意味します。


8
なぜ送信されている型は(おそらく)実装の詳細であるためだと思うので、それを非表示にしてコンパイラに実装の選択を処理させると、コードが読みやすくなります。そして、C ++機能を使用すると読みやすさが向上する場合は、なぜそうしないのですか?
ジュール

29
一つはさえでき#defineC11使用)(送信_Generic
デュプリケータ

16
@Julesプロジェクトで使用が許可されているC ++機能について非常に混乱しているためです。オブジェクトを含む潜在的な変更は拒否されますか?テンプレートはどうですか?C ++スタイルのコメント?もちろん、コーディングスタイルのドキュメントでこれを回避できますが、実行しているのが関数のオーバーロードの単純な場合だけである場合は、代わりにCを記述してください。
フィリップケンドール

25
@Phillip「C ++スタイルのコメント」は、10年以上にわたって有効なCです。
デビッドコンラッド

12
@Jules:送信されるタイプは、おそらく保険の見積もりを行うソフトウェアの実装の詳細ですが、OPsアプリケーションは、タイプとデータサイズが非常に重要なシリアル通信を行う組み込みシステムのようです。
-whatsisname

55

C ++の一部の機能のみを使用してCとして処理することは、まったく一般的ではありませんが、まったく前代未聞ではありません。実際、より厳密で強力な型チェックを除いて、C ++のすべての機能を使用しない人もます。彼らは単純にCを書いて(C ++とCの共通の交差点にのみ書くように注意して)、型チェックのためにC ++コンパイラで、そしてコード生成のためにCコンパイラでコンパイルします(またはC ++コンパイラをずっと使い続けます)。

Linuxは、人々がC ++コンパイラでLinuxをコンパイルできるようclassに、識別子をklassやなどに名前を変更するように定期的に要求するコードベースの例ですkclass。明らかに、C ++に対するLinusの意見を考えると彼らは常に撃ち落とされます。

あなたがしていることに何の問題もありません。C ++コンパイラのコード生成品質について本当に妄想している場合は、Comeau C ++などのコンパイラを使用できます。これは、ターゲット言語としてCにコンパイルし、Cコンパイラを使用します。そのようにして、コードのスポット検査を行って、C ++を使用すると予期しないパフォーマンスに敏感なコードが挿入されるかどうかを確認できます。ただし、オーバーロードだけではなく、文字通り異なる名前の関数(IOW、とにかくCで何をするのか)を自動的に生成します。


15

あなたのジレンマに対する客観的な答えは以下に依存します:

  1. C ++を使用する場合、実行可能ファイルのサイズが大幅に増加するかどうか。
  2. C ++を使用している場合、パフォーマンスに顕著な悪影響があるかどうか。
  3. Cコンパイラーのみが使用可能な別のプラットフォームでコードを再利用できるかどうか。

質問のいずれかに対する答えが「はい」である場合、データ型ごとに異なる名前の関数を作成し、Cを使用する方がよい場合があります。

すべての質問に対する答えが「いいえ」の場合、C ++を使用しない理由はわかりません。


9
2つの言語の共有サブセットで記述されたコードに対して、Cコンパイラよりも著しく悪いコードを生成するC ++コンパイラに出会ったことは一度もないと言わなければなりません。C ++コンパイラーはサイズとパフォーマンスの両方について悪い評価を得ますが、私の経験では、問題を引き起こしたのは常にC ++機能の不適切な使用です...特に、サイズが心配な場合は、iostreamを使用せず、使用しないでくださいテンプレートですが、それ以外は大丈夫です。
ジュール

@Jules:価値のあるもの(あまりないが、IMO)のために、CとC ++(メモリが提供される場合はTurbo C ++ 1.0)の単一のコンパイラとして販売されているものが同じ入力に対して著しく異なる結果を生成するのを見てきました。しかし、私が理解しているように、これは彼らが独自のC ++コンパイラを完成させる前であったため、外見上は1つのコンパイラのように見えますが、実際には2つの完全に別個のコンパイラがありました.1つはC用、もう1つはC ++用です。
ジェリー

1
@JerryCoffinメモリが機能する場合、Turbo製品はこれまで大きな評判を得たことはありません。そして、それが1.0バージョンだった場合、高度に洗練されていないことで言い訳される可能性があります。したがって、おそらくあまり代表的ではありません。
バーマー

10
@Barmar:実際、彼らはかなり長い間かなりの評判を得ていました。現在、彼らの評判が悪いのは、主に年齢が高いためです。彼らは同じヴィンテージの他のコンパイラと競争力がありますが、gcc 1.4(または何でも)で物事を行う方法についての質問を投稿する人はいません。しかし、あなたは正しいです-それは非常に代表的ではありません。
ジェリー

1
@Julesテンプレートさえも大丈夫だと主張します。一般的な理論にもかかわらず、テンプレートをインスタンス化してもコードサイズが暗黙的に増加することはありません。通常、テンプレートの関数が使用されるまでコードサイズは増加しません(この場合、サイズの増加は関数サイズに比例します)。静的変数の宣言。インライン化の規則は引き続き適用されるため、すべての関数がコンパイラーによってインライン化されるテンプレートを作成することができます。
ファラプ

13

C ++でコンパイルするだけで、より多くの機能にアクセスできるように質問します。これはそうではありません。C ++コンパイラでコンパイルするということは、ソースコードがC ++ソースとして解釈され、C ++がCとは異なる言語であることを意味します。両方の言語で受け入れられるが、異なる解釈のコードを書くことができます。

本当に必要なのが関数のオーバーロードだけである場合、C ++を導入することで問題を混乱させるポイントは実際にはありません。同じ名前の異なる関数の代わりに、パラメーターリストを区別し、異なる名前の関数を記述します。

客観的な基準については、

  1. C ++を使用する場合、実行可能ファイルのサイズが大幅に増加するかどうか。

実行可能ファイルは、C ++としてコンパイルされた場合、ビルドされた同様のCコードに比べてわずかに大きくなる可能性があります。少なくとも、C ++実行可能ファイルには、シンボルが実行可能ファイルに保持される範囲で、すべての関数名のC ++名前マングリングの疑わしい利点があります。(実際、それがそもそもあなたのオーバーロードを提供するものです。)違いがあなたにとって重要であるほど十分に大きいかどうかは、実験によって決定しなければならないものです。

  1. C ++を使用している場合、パフォーマンスに顕著な悪影響があるかどうか。

記述したコードと仮想的な純粋なCアナログのパフォーマンスに顕著な違いが見られるとは思いません。

  1. Cコンパイラーのみが使用可能な別のプラットフォームでコードを再利用できるかどうか。

私はこれに少し異なる光を投げます:C ++で構築しているコードを他のコードにリンクしたい場合は、その他のコードもC ++で記述してC ++で構築する必要があります独自のコードで特別なプロビジョニングを行う(「C」リンケージを宣言する)。これは、オーバーロードされた関数に対してはまったく実行できません。一方、コードがCで記述され、Cとしてコンパイルされている場合、他の人はそれをCおよびC ++モジュールの両方とリンクできます。この種の問題は通常、テーブルを回転させることで克服できますが、実際にはC ++を必要としないように思えるので、そもそもなぜこのような問題を受け入れるのでしょうか?


4
「実行可能ファイルは、C ++としてコンパイルされた場合、実行可能ファイルにシンボルが保持される範囲でわずかに大きくなる場合があります。」ただし、公平を期すために、適切な最適化ツールチェーンには、「リリース」ビルドでこれらのシンボルを削除するリンカオプションが必要です。つまり、デバッグビルドが肥大化するだけです。私はそれが大きな損失だとは思わない。実際、多くの場合、それは利点です。
コーディグレー

5

かつては、C ++コンパイラを「より良いC」として使用することがユースケースとして推奨されていました。実際、初期のC ++はまさにそれでした。基本的な設計原則は、必要な機能のみを使用でき、使用していない機能のコストが発生しないことです。そのため、overloadキーワードを使用してインテントを宣言することで関数をオーバーロードできます。プロジェクトの残りの部分は正常にコンパイルされるだけでなく、Cコンパイラが生成するよりも悪くないコードを生成します。

それ以来、言語は多少異なります。

mallocCコードのすべてが型の不一致エラーになります。動的メモリがない場合の問題ではありません。同様に、void明示的なキャストを追加する必要があるため、C内のすべてのポインターがトリップします。しかし...なぜあなたはそれをやっている、そのように ...あなたはより多くを備えてC ++を使用しての道を主導します。

そのため、追加の作業が必要になる場合があります。しかし、大規模なC ++採用へのゲートウェイとして機能します。数年後には、malloc呼び出しをに置き換え、newループ本体のコードのブロックを取り出して代わりにアルゴリズムを呼び出すだけで、1989年に書かれたように見えるレガシーコードに不満を抱き、代わりに安全でない偽のポリモーフィズムをbeりますコンパイラがそれを許可されていれば、ささいなことでした。

一方、Cで記述した場合はまったく同じであることがわかっているので、C ++の存在を考慮してCの代わりにCで記述するのは間違っていますか?答えが「いいえ」の場合、C ++のチェリーピック機能を使用することも間違っていません


2

多くのプログラミング言語には、それらの周りで発達する1つ以上の文化があり、言語が「あるべき」ものについて特定のアイデアを持っています。システムプログラミングに適した低レベル言語を使用することは可能であり、実用的で有用なはずですが、同様に適切なC ++の機能を使用して、このような目的に適したCの方言を拡張することもできますが、2つの言語を取り巻く文化はそうではありませんこのような合併を特に支持しています。

私は、C ++のいくつかの機能を組み込んだ組み込みCコンパイラを読みました。

foo.someFunction(a,b,c);

本質的に解釈される

typeOfFoo_someFunction(foo, a, b, c);

静的関数をオーバーロードする機能(名前のマングリングの問題はエクスポート時にのみ発生します関数がオーバーロードされています)。Cコンパイラがリンクおよびランタイム環境に追加要件を課すことなくこのような機能をサポートできない理由はありませんが、多くのCコンパイラは、環境負荷を回避するためにC ++からのほとんどすべてを再帰的に拒否します。そのようなコストを課さない機能さえも拒否します。一方、C ++の文化は、その言語のすべての機能をサポートできない環境にはほとんど関心がありません。Cのカルチャがそのような機能を受け入れるように変更されない限り、またはC ++のカルチャが変更されて軽量サブセットの実装が促進されない限り、「ハイブリッド」コードは両方の言語の制限の多くに苦しみがちですが、その能力は制限されます複合スーパーセットで動作することの利点。

プラットフォームがCとC ++の両方をサポートしている場合、C ++をサポートするために必要な追加のライブラリコードにより、実行可能ファイルが多少大きくなる可能性がありますが、効果は特に大きくはありません。C ++内での「C機能」の実行は、特に影響を受けないでしょう。より大きな問題は、CおよびC ++オプティマイザーがさまざまなコーナーケースを処理する方法です。Cのデータ型の動作は、その中に格納されているビットの内容によって大部分が定義され、C ++には構造のカテゴリ(PODS--Plain Old Data Structures)があり、そのセマンティクスも同様に大部分が格納されているビットによって定義されます。ただし、CとC ++の両方の標準では、格納されたビットが示す動作とは逆の動作が許可される場合があり、「格納されたビット」動作の例外は2つの言語で異なります。


1
興味深い意見ですが、OPの質問には対応していません。
R Sahu

@RSahu:言語を取り巻く「文化」に適合するコードは、サポートしていないコードよりも、より適切にサポートされ、さまざまな実装により簡単に適応できる傾向があります。CとC ++の文化はどちらも、OPが示唆する種類の使用法に反するものです。特定の質問に関して、さらに具体的なポイントを追加します。
-supercat

1
C ++標準委員会には、廃棄されたと主張する「あまり関心のない」状況を正確に解決することを目的とした組み込み/金融/ゲームグループがあります。
Yakk

@Yakk:私の興味は主にCにあるので、私はC ++の世界をあまり厳密に追跡していないと告白します。より多くの埋め込み方言に向けた努力があったことは知っていますが、それらが本当にどこでも手に入るとは思っていませんでした。
-supercat

2

考慮すべきもう1つの重要な要素は、コードを継承する人です。

その人は常にCコンパイラでCプログラマーになるのでしょうか?そうだと思います。

その人は、C ++コンパイラを使用するC ++プログラマでもありますか?コードをC ++固有のものに依存させる前に、このことについて合理的に確認したいと思います。


2

多態性は、C ++が無料で提供する非常に優れた機能です。ただし、コンパイラを選択する際に考慮する必要がある他の側面があります。Cには多型に代わるものがありますが、それを使用すると眉が隆起する可能性があります。その変数関数については、変数関数チュートリアルを参照してください

あなたの場合、それは次のようになります

enum serialDataTypes
{
 INT =0,
 INT_P =1,
 ....
 }Arg_type_t;
....
....
void transmit(Arg_type_t serial_data_type, ...)
{
  va_list args;
  va_start(args, serial_data_type);

  switch(serial_data_type)
  {
    case INT: 
    //Send integer
    break;

    case INT_P:
    //Send data at integer pointer
    break;
    ...
   }
 va_end(args);
}

私はフィリップスのアプローチが好きですが、それはあなたのライブラリにたくさんの呼び出しを散らかしています。上記により、インターフェースはきれいです。それには欠点があり、最終的には選択の問題があります。


可変引数関数は、主に、引数の数その型の両方が可変であるユースケースに役立ちます。それ以外の場合は、必要ありません。特に、特定の例では過剰です。受け入れる通常の関数を使用する方が簡単だろうArg_type_tvoid *データを指します。そうは言っても、はい、データ型を示す引数を(単一の)関数に与えることは、実際に実行可能な代替手段です。
ジョンボリンジャー

1

いくつかの異なるタイプの「関数」を静的にオーバーロードする特定のケースでは、代わりに_GenericマクロマシンでC11を使用することを検討してください。限られたニーズには十分かもしれません。

フィリップケンドールの答えを使用すると、次のように定義できます。

#define transmit(X) _Generic((X),      \
   unsigned char*: transmit_uchar_buffer, \
   char*: transmit_char_buffer,           \
   unsigned char: transmit_uchar,         \
   char: transmit_char) ((X))

(上記の4つのタイプのうち)transmit(foo) のタイプをコード化しますfoo

あなただけを気にした場合、GCC(と互換性のある、例えばクラン)コンパイラには、その検討することもでき__builtin_types_compatible_pwtthそのtypeof延長。


1

関数のオーバーロードのためだけにC ++コンパイラを使用するのは悪い習慣ですか?

私見の観点からはい、両方の言語が大好きなので、これに答えるために統合失調症になる必要がありますが、それは効率とは関係ありませんが、言語の安全性と慣用的な使用に似ています。

C側

Cの観点からすると、関数のオーバーロードを使用するためだけにコードにC ++を必要とするのは非常に無駄です。C ++テンプレートを使用した静的なポリモーフィズムに利用しない限り、まったく異なる言語への切り替えと引き換えに得られるこのような取るに足らない構文上の砂糖です。さらに、関数をdylibにエクスポートしたい場合(実際の懸念かもしれませんが、そうでない場合もあります)、すべての名前がマングルされたシンボルを使用して広範囲に消費することは、もはや実際にはできません。

C ++側

C ++の観点からは、関数のオーバーロードを伴うCのようなC ++を使用しないでください。これは文体的な教義ではなく、日常のC ++の実用化に関連したものです。

あなたの通常の種類のCコードは、でコピーctorのようなものを禁止しているC型システムに対して作業している場合にのみ、合理的に健全で「安全に」書くことができますstructs。あなたは次のように莫大な価値があるC ++の豊かな多くのタイプのシステム、日常の機能で作業したらmemsetmemcpyあなたがすべての時間に傾くべき機能にはなりません。代わりに、それらはペストのように一般的に避けたい関数です。C++型では、コピーしてシャッフルして解放する生のビットやバイトのように扱うべきではないからです。コードmemsetが現時点でプリミティブやPOD UDTのようなものだけを使用している場合でも、使用するUDTに誰かがctorを追加する瞬間(たとえば、std::unique_ptrメンバー)そのような関数または仮想関数またはそのようなものに対して、未定義の動作の影響を受けやすい通常のCスタイルのコーディングをすべてレンダリングします。ハーブサッター自身からそれを取ります:

memcpymemcmp型システムに違反します。memcpyオブジェクトのコピーに使用することは、コピー機を使用してお金を稼ぐようなものです。memcmpオブジェクトの比較に使用することは、ヒョウのスポットを数えてヒョウを比較するようなものです。ツールと方法は仕事をしているように見えるかもしれませんが、それらは容認できるようにするには粗すぎます。C ++オブジェクトはすべて情報隠蔽に関するものです(ソフトウェアエンジニアリングでおそらく最も収益性の高い原則、項目11を参照):オブジェクトはデータを隠し(項目41を参照)、コンストラクターと割り当て演算子を介してそのデータをコピーするための正確な抽象化を考案します(項目52から55を参照) 。それをすべてブルドージングするとmemcpy、情報隠蔽の重大な違反となり、多くの場合、メモリとリソースのリーク(せいぜい)、クラッシュ(悪化)、または未定義の動作(最悪)につながります-C ++コーディング標準。

哲学はC ++でコードを記述している場合にのみ当てはまるため、多くのC開発者はこれに異議を唱えます。あなたは、最も可能性が高いしているあなたのような機能を使用する場合に非常に問題のあるコードを書くmemcpyすべての時間C ++のように構築したコードでは、しかし、あなたはそれを行う場合、それは完全に罰金ですCで。2つの言語は、型システムの違いにより、この点で大きく異なります。これら2つの共通の機能のサブセットを見て、特にC ++側で一方が他方のように使用できると信じているのは非常に魅力的ですが、C +コード(またはC--コード)は一般にCとC ++コード。

同様に、たとえば、mallocスローできるC ++関数を直接呼び出すことができる場合、Cスタイルコンテキスト(EHを意味しない)で使用しないでください。これは、関数の結果として暗黙的な終了点があるためです。freeそのメモリに到達する前にCスタイルのコードを書くのを効果的にキャッチできない例外。ですから、C ++のように構築し、ファイル持っている時はいつでも.cpp拡張子または何、それはのようなもののすべてのこれらのタイプを行いますがmallocmemcpymemsetqsortなど、その後、まだプリミティブ型でのみ動作するクラスの実装の詳細でない限り、さらに下流の問題を求めていますが、その時点で例外処理を行う必要があります。あなたがC ++のコードを書いている場合は、代わりに、一般的にRAIIに依存しているとのようなものを使用したいvectorunique_ptrshared_ptr、などを、そして可能な場合、すべての通常のCスタイルのコーディングを避けます。

CおよびX線データタイプのカミソリの刃で遊ぶことができ、チームで副次的な損傷を引き起こす傾向がなく、そのビットとバイトで遊ぶことができる理由は(あなたはまだどちらにしても本当に自分を傷つけることができますが)型はできますが、それらができないことのために。Cの型システムを拡張して、ctor、dtor、vtablesなどのC ++機能と例外処理を含めると、すべての慣用的なCコードが現在よりはるかに危険になり、新しい種類のC ++で見られるように、まったく異なるスタイルのコーディングを奨励する哲学と考え方が進化します。C++では、たとえば、RAII準拠のリソースとは対照的に、メモリを管理するクラスに生のポインター不正を使用することも検討していますunique_ptr。その考え方は、絶対的な安全感覚から発展したものではありません。型システムで許可されているだけの例外処理のような機能に対してC ++が特に安全である必要があるものから進化しました。

例外安全性

繰り返しになりますが、あなたがC ++の土地にいる瞬間、人々はあなたのコードが例外安全であることを期待するでしょう。コードはすでにC ++で記述およびコンパイルされておりstd::vector, dynamic_cast, unique_ptr, shared_ptr、コードによって直接または間接的に呼び出されるコードでを使用するなど、コードはすでに「想定」されているため、無害であると信じて、将来あなたのコードを維持する可能性がありますコード。その時点で、物事がスローされる可能性に直面する必要があります。次に、次のような完全に素晴らしく素敵なCコードを取得します。

int some_func(int n, ...)
{
    int* x = calloc(n, sizeof(int));
    if (x)
    {
        f(n, x); // some function which, now being a C++ function, may 
                 // throw today or in the future.
        ...
        free(x);
        return success;
    }
    return fail;
}

...壊れています。例外に対して安全になるように書き換える必要があります。

int some_func(int n, ...)
{
    int* x = calloc(n, sizeof(int));
    if (x)
    {
        try
        {
            f(n, x); // some function which, now being a C++ function, may 
                     // throw today or in the future (maybe someone used
                     // std::vector inside of it).
        }
        catch (...)
        {
            free(x);
            throw;
        }
        ...
        free(x);
        return success;
    }
    return fail;
}

キモい!これが、ほとんどのC ++開発者が代わりにこれを要求する理由です。

void some_func(int n, ...)
{
    vector<int> x(n);
    f(x); // some function which, now being a C++ function, may throw today
          // or in the future.
}

上記は、C ++開発者が一般に承認する種類のRAII準拠の例外セーフコードです。これは、関数がの結果として暗黙的な終了をトリガーするコード行をリークしないためですthrow

言語を選択してください

RAII、例外安全性、テンプレート、OOPなどでC ++の型システムと哲学を採用するか、生のビットとバイトを中心に展開するCを採用する必要があります。これらの2つの言語の間で不浄な結婚を形成するべきではなく、それらを別々の言語に分けて、それらを一緒に曖昧にするのではなく、非常に異なって扱うべきではありません。

これらの言語はあなたと結婚したいです。あなたは通常、両方でデートして浮気するのではなく、どちらかを選択する必要があります。または、あなたは私のような一夫多妻主義者であり、両方と結婚することができますが、お互いに時間を過ごすときは完全に思考を切り替えて、お互いに戦わないようにお互いを十分に離しておく必要があります。

バイナリサイズ

好奇心から、今すぐフリーリストの実装とベンチマークを試し、C ++に移植してみました。

[...] Cコンパイラを使用していないので、Cでどのように見えるかわかりません。

...そして、バイナリサイズがC ++としてビルドするだけで膨張するかどうかを知りたいと思っていました。ひどい場所に明示的なキャストを振りかける必要がありました(アロケーターやCでのデータ構造のような低レベルのものを実際に書くのが好きな理由の1つ)が1分しかかかりませんでした。

これは単純なコンソールアプリケーションのためのMSVC 64ビットのリリースビルドを比較し、いずれかのC ++の機能を使用していないコードで、演算子のオーバーロードしてもいませんでした- Cでそれを構築し、使用して、たとえば、間単に違い<cstdlib>の代わり<stdlib.h>とそのようなことですが、バイナリサイズとの差がゼロになったことに驚きました!

バイナリは9,728、Cでビルドされた場合はバイトであり9,278、C ++コードとしてコンパイルされた場合もバイトでした。私は実際にそれを期待していませんでした。EHのようなものは、少なくとも少しは追加されると考えました(少なくとも100バイトは異なると考えられていました)が、たぶん、 C標準ライブラリを使用すると、何もスローされません。私は何かを考えましたRTTIのように、どちらの方法でもバイナリサイズに少し追加されます。とにかく、それを見るのはちょっとクールでした。もちろん、この1つの結果から一般化する必要はないと思いますが、少なくとも少し感銘を受けました。また、ベンチマークに影響を与えることはありませんでした。当然のことながら、同じ結果のバイナリサイズは、結果のマシン命令も同じになると思います。

とはいえ、上記の安全性とエンジニアリングの問題でバイナリサイズを気にする人はいますか?繰り返しになりますが、言語を選択して、その哲学を受け入れようとするのではなく、その哲学を受け入れます。それがお勧めです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.