【結構迷う】C vs. C++【どっちで行こうか】
■ このスレッドは過去ログ倉庫に格納されています
0001デフォルトの名無しさん
2008/04/06(日) 03:17:49どちら一方をどっぷりと使っている人にとっては、かなり大きな
壁を感じると思います。
そこで、「C/C++」な人でも「C派」「C++派」に分かれて、それぞれの
観点からどちらの言語がより良いか、議論してみましょう。
主観的、客観的意見なんでも構いません。ただし建設的な議論に
なるよう、理由も添えてお願いします。
ルール
1.Java、C#などの「C/C++」以外は論外。これらについて言及している
レスは無視してください。
2.速い、遅いなどの議論は極力説得力のある根拠、ソース(情報源)
などを提示してください。
3.特定のOS、開発環境を理由に挙げたり、叩いたりしないでください。
たとえば、「Linuxの人は…」や「VC++ってやつは…」などは禁止。
4.標準、準標準のライブラリに関しては、その言語を使う場合常に
ついてまわるので言及をOKとします。
5.どちらか一方しか使ったことのない人は、その旨を述べた上で
意見をお願いします。
6.その他、明らかな煽りや無意味な書き込みも無視でお願いします。
0153デフォルトの名無しさん
2011/02/19(土) 09:14:260154デフォルトの名無しさん
2011/02/19(土) 09:20:22それって結局内部的に計算してるってことだよね?
0155デフォルトの名無しさん
2011/02/19(土) 09:24:390156デフォルトの名無しさん
2011/02/19(土) 09:26:170157デフォルトの名無しさん
2011/02/19(土) 09:29:06文字数のカウントが速いんだとか、そういった分かり易いシンプルな説明って無いの?
0158デフォルトの名無しさん
2011/02/19(土) 09:41:01午後の部を待つか・・・
0159デフォルトの名無しさん
2011/02/19(土) 09:53:300160デフォルトの名無しさん
2011/02/19(土) 11:28:50string同士の操作はお互いに文字数が分かってるのでカウントしなおさない。
const char* が含まれる場合は1回だけstrlen相当の処理が使われる。
0161デフォルトの名無しさん
2011/02/19(土) 15:41:49どうもありがとう。
文字列のコピーや連結の時にショートカットが出来ると言う事かな。
それだけの事であれば、文字列長のカウントがホットスポットになった場合に、
C で同じ様な実装をするのは雑作無い事だよね。
ある文字列の先頭の 5 文字を除いた文字列を関数に渡したいと言った時に、
C ならポインタを 5 文字分だけずらして渡してあげればいいだけだけど、
C++ の文字列では、文字数情報を記憶しないといけないので、わざわざ
substr() みたいな関数呼び出しにしないといけないんだよね?
こっちのオーバーヘッドの方が無駄じゃないの?
0162デフォルトの名無しさん
2011/02/19(土) 16:16:54string.c_str() + 5 とかで渡せる。(ちゃんとnullストップになってる。)
挿入したい場合は挿入用のメンバ関数がある。
0163デフォルトの名無しさん
2011/02/19(土) 16:20:57単に良く分からないから嫌っているってだけのことが
*非常に*多いのがこのスレを見ていても良く分かるね
よく分かっている道具を使うのは間違いじゃないし正しい態度でもあるが、
よく知らないものを知らないくせにdisるのはバカのやることだな
0164デフォルトの名無しさん
2011/02/19(土) 16:29:03その関数が C の文字列を受け取る関数ならその通りだけど、
C++ string を受け取る関数なら、やはり何らかの事前処理が
必要になるよね
>>163
俺はこれが気になったから質問してるだけだよ
>これは、単に、Cで普通に使われる文字列はヌル文字の番兵で終端を表しているだけで
>自分の長さを知らないデータ構造なので、
>文字列長を知るにはいちいちO(n)のstrlen()を利用する必要があり
>それ自体が非効率な仕組みだ、と言えばよかったのにな
C++ の文字列って C の文字列を dis れる程、効率的な物
なのか知りたくなってね
0165デフォルトの名無しさん
2011/02/19(土) 16:33:12効率が気になるなら試せよ。
0166デフォルトの名無しさん
2011/02/19(土) 16:36:37そんな良い物ではないよw
for内でstrlen使っちゃうような、うっかり八兵衛には効率的なのかもしれないが。
0167デフォルトの名無しさん
2011/02/19(土) 16:37:09>>140 がああまで言う理屈が分からないと、テストパターンも作れないでしょ
0168デフォルトの名無しさん
2011/02/19(土) 16:40:28だから挿入用や上書き用のメンバも何種類もある。
何文字目から始める&終わるか引数で渡せる。
Cのポインタみたいなノリで書きたい場合は、イテレータという物もある。
0169デフォルトの名無しさん
2011/02/19(土) 16:41:10要は、適材適所なんだからどの方式も一概に否定したもんじゃないさ。
0170デフォルトの名無しさん
2011/02/19(土) 16:46:30ありがとう。やっぱりそうなんですね。
C++ が実行効率に神経を注いでるのは聞いていたので、
何かいい仕組みがあるのかもと期待しちゃいました。
>>168
今していたのは C++ と C の文字列の計算量の話
その何種類もあるメンバも内部的に計算してるわけでしょ
そしたらその分の計算量が発生するでしょ
繰り返しになるから、これ以上は説明しませんので、
お願いします・・・
0171デフォルトの名無しさん
2011/02/19(土) 16:47:04C で C++ っぽくは書けないお。
C++ だからって string を使わにゃならんわけじゃなし。
0172デフォルトの名無しさん
2011/02/19(土) 16:49:15ただし、>>168の言っているように、C++では本当にジェネリックなアルゴリズムとして
記述する場合はSTLのようにテンプレートとiteratorが使われる
この場合は本質的に効率はポインタと同等でありながら、データ構造の内部表現を
問わない
charのストリーム、charのリスト、charの配列、stringを全く同じテンプレート関数に
適用できるということだ
Cならアダプタか、別々の実装を書く必要があるだろうな
また、特にstringで受ける必要が無い関数なら、C++であってもconst char *
もよく使われるよ
0173デフォルトの名無しさん
2011/02/19(土) 16:52:07文字数のみを考えるなら、こんな感じの構造体と
それを操作する関数を用意してあげれば良いだけ
typedef struct { int len; char str[] } string;
0174デフォルトの名無しさん
2011/02/19(土) 16:52:59ある std::string から先頭 5 文字を取り除いたものを std::string として渡すんなら、
substr() するか先頭を erase() したものを渡すことになる。そんなに効率的じゃない。
でもこれを以って「やっぱり C のほうがいい」なんてことにはならないでしょ?
先頭 5 文字削るのは直感的で効率のいいコードになるけど、後ろ 5 文字削るとか
途中 5 文字削るとか、ちょっとした違いでコードも効率も全然違ったものになってしまう
のは理不尽だよ。
ちなみに、そういう処理を効率的にするためのものとして、標準じゃないけど
StringPiece ってのがあったりする。
http://d.hatena.ne.jp/shinichiro_h/20100823
> http://src.chromium.org/viewvc/chrome/trunk/src/base/string_piece.h
C で同様の機能のライブラリを作ることもできるだろうけど、これより良いものには
できないでしょ。
0175デフォルトの名無しさん
2011/02/19(土) 16:53:29ポインタ+位置差分の加算等のことを言ってるのなら、
イテレータでポインタライクに操作できるんだって。
先頭の位置は変数(ポインタ)で保持される。
0176デフォルトの名無しさん
2011/02/19(土) 16:55:47CではC++と違ってカプセル化によってデータ構造の整合性が常に保たれることを
保障することが難しい
Cでカプセル化したければ、opaqueポインタ経由でユーザにアクセスさせるように
してデータ構造を隠すしかないが、stringクラス的な用途ではそうするのは非効率だ
この辺も、Cでパスカル文字列が採用されなかった理由のひとつだろうと思う
ただの創造だが
0177デフォルトの名無しさん
2011/02/19(土) 16:56:29うんそういうこと。でもそれを全ての文字列操作関数に対応させたり、
さらには非標準の文字列操作ライブラリにも広く対応させたり
自分の力だけでやるのは大変でしょ?
そういう標準化、規格化として意味があるわけです。
0178デフォルトの名無しさん
2011/02/19(土) 16:56:45関数に渡す文字列の話だよ?
0179デフォルトの名無しさん
2011/02/19(土) 16:58:39だから、関数が「stringで受けるように作ってあれば」
部分文字列を渡したければsubstrを使う必要があり、それがO(n)なのはその通り
だが、C++で関数をそう作る必要はどこにもない
iteratorで受けてもポインタで受けてもいい
要求に応じて適した選択が選べるということ
0180デフォルトの名無しさん
2011/02/19(土) 17:01:08C の方が良いと主張したいわけじゃないです。
C++ の文字列の方が優れているという人がいたので、
それは誤解じゃないの? と聞いてみた次第です。。。
0181デフォルトの名無しさん
2011/02/19(土) 17:02:51自分で作る関数に付いては、もちろんその場で一番効率が良い実装をするのが
当たり前だと思います
0182デフォルトの名無しさん
2011/02/19(土) 17:06:53標準の文字列型として、所有権・寿命の管理を気にしなくても使えるようにするのが主目的だから、
効率だけ見てどっちが優れているかを考えるのは不毛なこと。
その中でも、文字列を変更しない間に繰り返し長さを得る場合には std::string のほうが効率的な
「こともある」と挙げているのが元の記事。はじめから、すべての場合で効率的であると主張して
いたわけじゃない。
0183デフォルトの名無しさん
2011/02/19(土) 17:08:53書けば大抵Cのほうが速いだろうけどな
重要な違いが出るかどうかはともかく
ただまあ、明らかにC++のが速いことが分かってるものもいくつかある
qsort()に対するstd::sort()とか
0184デフォルトの名無しさん
2011/02/19(土) 17:17:59と思ったほうが楽なこともある
ないよりはあるほうがいい場合もあるが、すべての場合ではない
0185デフォルトの名無しさん
2011/02/19(土) 17:19:300186デフォルトの名無しさん
2011/02/19(土) 17:36:300187デフォルトの名無しさん
2011/02/19(土) 17:44:28設定ファイルを読み書きするようなところではstd::stringで、
必要なら外部の正規表現ライブラリでもなんでも使って、
こういう風に選択できるところがC++のいいところなんだってば。
ちょっとしたテキストビューワが必要なときに、テキストエディタで要求されるような
行単位のリスト構造を一一作らないときがすまないようなロートルCプログラマには
理解し難いことなのかもしれないけれど。
0188デフォルトの名無しさん
2011/02/19(土) 17:46:49GC もあるし GUI も完備
0189デフォルトの名無しさん
2011/02/19(土) 20:01:17.96Cで書かなきゃならん部分だけCで書いて、
それ意外の部分はshなりPerlなりPythonなりで
書くのがCプログラマなんで、その指摘は的外れかと。
C++プログラマはC++の中だけで機能を選択するが、
Cプログラマは言語の枠を超えて機能を選ぶ。
0190デフォルトの名無しさん
2011/02/19(土) 20:08:05.79なんで C++ プログラマは「shなりPerlなりPythonなり」を使わないと思ってるの?
0191デフォルトの名無しさん
2011/02/19(土) 20:10:24.84C で 187 みたいなことできるの?
0192デフォルトの名無しさん
2011/02/19(土) 20:11:15.88ロートルだからじゃね?
0193デフォルトの名無しさん
2011/02/19(土) 20:15:44.66慣れるまで大変で。
0194デフォルトの名無しさん
2011/02/19(土) 20:38:32.190195デフォルトの名無しさん
2011/02/20(日) 00:38:01.750196デフォルトの名無しさん
2011/02/20(日) 04:15:04.36実装読めよ馬鹿。
0197デフォルトの名無しさん
2011/02/20(日) 04:17:12.610198デフォルトの名無しさん
2011/02/20(日) 08:37:19.59C++でCに追加された構文的拡張は、
それらの言語ではより良く(より簡潔に、またはより一貫性のある形で)
実装されているので、それらの言語も使える場合
C++を使う理由は実行速度くらいしかない
(Cと併用できるならそれすら無い)
0199デフォルトの名無しさん
2011/02/20(日) 08:54:53.51手間は増えると思うんだ。
0200デフォルトの名無しさん
2011/02/20(日) 08:56:54.712、3個の言語を組み合わせる程度なら追加の手間はないと思うよ
0201デフォルトの名無しさん
2011/02/20(日) 09:10:11.44把握する手間に比べれば、どってことないよな。
0202デフォルトの名無しさん
2011/02/20(日) 09:17:05.830203デフォルトの名無しさん
2011/02/20(日) 09:19:43.210204デフォルトの名無しさん
2011/02/20(日) 09:24:58.920205デフォルトの名無しさん
2011/02/20(日) 09:43:01.170206デフォルトの名無しさん
2011/02/20(日) 11:45:57.19え?
>189 にある「Cで書かなきゃならん部分」ってのも実行速度が欲しいところぐらいじゃないの?
他になんかある?あったとしてもC++では書けない、なんてことあるの?
0207デフォルトの名無しさん
2011/02/20(日) 14:50:52.10C PG : 「gets() の事ならもうずっと誰も使っていないし、2012 年に予定されている次の仕様で削除される予定だぞ」
0208デフォルトの名無しさん
2011/02/20(日) 18:24:03.29このスレッドを読んできて、それでも「書けるか書けないか」
が争点だと思えるなら理解力が無さすぎる。
CのほぼスーパーセットのC++で書けないなんてことが
あるわけないだろ。
問題点になっているのは、いわば「読みやすさ」。
0209デフォルトの名無しさん
2011/02/20(日) 18:42:39.03なんで C++ で書くと読みやすさが損なわれると思ってるの?
0210デフォルトの名無しさん
2011/02/20(日) 18:48:15.29ロートルの人が読めるかどうかです
0211デフォルトの名無しさん
2011/02/20(日) 19:03:36.830212デフォルトの名無しさん
2011/02/20(日) 19:21:18.05その時々で流行のパラダイム(OOPとか)をサポートする
構文糖が節操無く追加された結果、言語のデザインに一貫性が無い。
一貫性が無いから、構文糖がどのような暗黙的コードを生成するかは
単純に暗記するしかなく、さらに複数の異なる暗黙的コードの相互作用が
様々な罠を張ってて、簡単に自分の足を打ち抜けるようになってる。
ただ罠を避けるためだけの本(Effective C++とか)が必読本の時点で
何かおかしいと感じるべき。
こんな言語が読みやすいというなら、読みやすさは
プログラミング言語の評価基準にならないよ。
0213デフォルトの名無しさん
2011/02/20(日) 19:33:01.14まあ、確かに C++ は罠が多いけど
ヤバい所は使わずに美味しいところだけ使うこともできる。
C は、できないよね。
0214デフォルトの名無しさん
2011/02/20(日) 19:37:40.43純粋仮想関数が = 0 って糞ワラタw
0215デフォルトの名無しさん
2011/02/20(日) 19:44:11.93そのコードがどう実行されるかが比較的判りやすい言語だ。
もちろんマクロやグローバル変数等を使ってそうじゃなくすることも可能だけど、
そういうコードは「悪いコード」だとする文化がある。
一方、C++はコードをより広いコンテクストに依存させる構文糖
を積極的に追加する上に、どういうコードが良いコードか
(例えば、ある構文糖をどういう場合に「使わない」かについて)
の文化すら存在しないので、あるコードが何をしているか把握するのに
ずっと多くのコードを読まなきゃいけない。
だからC++は読み難いんだよ。
0216デフォルトの名無しさん
2011/02/20(日) 19:45:12.140217デフォルトの名無しさん
2011/02/20(日) 19:48:48.72Cだって正しく使おうと思ったら暗記しないといけないことは山ほどある。
未定義動作とか副作用完了点とか。 C FAQ にいろいろ載ってるよね。
> 複数の異なる暗黙的コードの相互作用が様々な罠を張ってて
これは、なんのことだろう?ひとつでも例を挙げてみてもらえないか?
0218デフォルトの名無しさん
2011/02/20(日) 19:50:33.20> もちろんマクロやグローバル変数等を使ってそうじゃなくすることも可能だけど、
> そういうコードは「悪いコード」だとする文化がある。
なんで C++ だとそんなのが受け入れられると思ってるの?
0219デフォルトの名無しさん
2011/02/20(日) 19:51:35.890220デフォルトの名無しさん
2011/02/20(日) 19:53:33.870221デフォルトの名無しさん
2011/02/20(日) 19:54:45.800222デフォルトの名無しさん
2011/02/20(日) 19:59:12.96例えば、コンストラクタの中から例外を出すと
デストラクタが呼ばれないから、
常にデストラクタが呼ばれる、という前提でプログラムを書くと
リークしちゃう、とか。
じゃあコンストラクタでは例外送出しなきゃいいんじゃね?と思うと
コピーコンストラクタでのエラーは例外じゃなきゃ拾えないし、とか
どんだけ落とし穴掘ってれば気が済むんだよ。
0223デフォルトの名無しさん
2011/02/20(日) 20:06:42.84C++ プログラマは経験の浅いやつって
前提があるみたいだな
0224デフォルトの名無しさん
2011/02/20(日) 20:11:25.78継承と例外とコンストラクタだ
0225デフォルトの名無しさん
2011/02/20(日) 20:15:33.58C にしろ C++ にしろ、言語のダメな所が認められないプログラマはまずいよな
0226デフォルトの名無しさん
2011/02/20(日) 20:21:31.86それの説明に妙な前提があるのがおかしいんだよ
0227デフォルトの名無しさん
2011/02/20(日) 20:23:05.31「コンストラクタの完了でオブジェクトの構築完了」っていうオブジェクトモデルを把握すれば
自然なことなんだけどね。
FAQ にも載ってる。
http://www.parashift.com/c++-faq/exceptions.html#faq-17.10
日本語で充実した FAQ が無いのが悪いんかな?
0228デフォルトの名無しさん
2011/02/20(日) 20:24:04.23前に挙がっていた例では、C++ を支持している人は C については素人っぽかったよ
0229デフォルトの名無しさん
2011/02/20(日) 20:24:06.05× 相互作用の原因は三つある
○ 俺の良く知らない機能が三つある
0230デフォルトの名無しさん
2011/02/20(日) 20:27:03.07どっちの言語がどうという訳ではないが。
0231デフォルトの名無しさん
2011/02/20(日) 21:26:39.59Cの副作用完了点について知らないなら、
C++で&&とかの演算子オーバーロードが
何故禁じ手か絶対理解できないな。
しかもショートサーキットの概念は特定の言語に
依存しない一般的なものだけど、&&とかがオーバーロードで
副作用の仕方が変わるのは"たまたま"演算子オーバーロードが
関数に変換されるというC++固有の性質だから。
つーか、流石にその程度なら皆正しく使えてるだろ。
未定義動作、特に整数オーバーフローとかCにも難しい罠が
あるのは否定しない。
0232デフォルトの名無しさん
2011/02/20(日) 21:52:40.83単純な原因から複雑な結果が生じているのだから
原因を良く知らないから悪いとか、原因を良く知れば解決するという問題ではない。
0233デフォルトの名無しさん
2011/02/20(日) 21:57:37.750234デフォルトの名無しさん
2011/02/20(日) 22:26:05.05通常書くものが書かれていない場合はコメントを書く。
そういうパターンを整理すれば良いような気がする。
C++には、何も書かなくても自動的に処理する機能が多いが
その機能を使わないから何も書かなかったのか、
使うから何も書かなかったのか分からない。
0235デフォルトの名無しさん
2011/02/20(日) 22:33:36.08> C++には、何も書かなくても自動的に処理する機能が多いが
具体的に。
0236デフォルトの名無しさん
2011/02/21(月) 08:52:00.83フグかよと
0237デフォルトの名無しさん
2011/02/21(月) 09:19:11.05例えば、仮想関数もデフォルト引数も、共にどうってことない
判りやすい概念だが、C++で両方同時に使うと
仮想関数自体は動的型で呼び出し先が決まるのに、
デフォルト引数は静的型で解決される、という
悪意を疑いたくなる罠が存在する。
これも個々は単純だが、結果が複雑な例だな。
0238デフォルトの名無しさん
2011/02/22(火) 12:40:27.23うーん。個人的にはあたりまえに思うんだけど、慣れちゃってるからなんだろうなー。
0239デフォルトの名無しさん
2011/02/22(火) 13:45:14.460240デフォルトの名無しさん
2011/02/22(火) 15:57:22.02デフォルトコピーコンストラクタとデストラクタのコンボとか。
あまりにも有名なトラップなんで、嵌るやつもいないかもしれんが。
0241デフォルトの名無しさん
2011/02/22(火) 21:50:46.99そもそも継承のおかげでアップキャストは当たり前で
例外を使えば型を変更しなくてもエラーに関する仕様を変更できる
型とは一体なんだったのか
0242デフォルトの名無しさん
2011/02/23(水) 00:39:27.54> 例外を使えば型を変更しなくてもエラーに関する仕様を変更できる
これどういうこと?
0243デフォルトの名無しさん
2011/02/23(水) 14:20:18.88デフォルトがユーザ定義型で暗黙的型変換可能って、誰得だよ。
0244デフォルトの名無しさん
2011/02/23(水) 15:13:31.78C++使うのやめようかと思うから困る
0245デフォルトの名無しさん
2011/02/23(水) 15:15:06.01もうC++使ってるんなら手遅れでは
罠が多すぎて習得するのが大変すぎるという話題だからな
0246デフォルトの名無しさん
2011/02/23(水) 15:26:08.43C++0xの右辺値参照が難しすぎて、
俺には理解できる気がしないのだよ。
C++から足を洗ういい機会な気がしてな……
0247デフォルトの名無しさん
2011/02/23(水) 15:31:18.13(うっかり基底クラスの配列に継承クラスを入れてしまいながら)
0248デフォルトの名無しさん
2011/02/23(水) 15:43:06.24そうなるとクラスと例外とテンプレートは使うしなー。
実際、C++の機能で取り除けるものが思い浮かばん。
0249デフォルトの名無しさん
2011/02/23(水) 16:07:54.96"Modern move semantics"とかそんな感じの本が
多分出版されるから、大丈夫だよ!
0250デフォルトの名無しさん
2011/02/23(水) 21:39:37.60一番メリットが無いと思うわ。
Cと比べて特に生産的というわけでもなく、
C++のグロ文法とABI不在の問題点は引き継ぐとか。
どこがbetterなのかと。
0251デフォルトの名無しさん
2011/02/23(水) 22:14:39.960252デフォルトの名無しさん
2011/02/24(木) 03:05:10.83C++ PG B : 「STL 便利じゃん」
C++ PG C : 「クラス便利じゃん」
C++ PG D : 「テンプレート便利じゃん」
C++ PG E : 「例外便利じゃん」
C++ PG F : 「名前空間便利じゃん」
C PG : 「それもう "better" C じゃなくて C++ じゃん・・・」
■ このスレッドは過去ログ倉庫に格納されています