一般的にC++が難しいと言われている理由はなんでしょうか?
[自分の考え]
1, 記述の仕方がバラバラ(一貫性?がない)
以前、以下のような質問をしました。
C++の修飾子や指定子について
この質問における最大の疑問は「指定子や修飾子の書き方がてんでバラバラ」というところです。
C++
1★ int ● func ◆ { 2 3}
★・・・返り値への修飾(static constなど)
● ・・・関数への修飾(inline noexceptなど) と言った具合にですね。まとまっていると非常に分かりやすいと思うんですが・・・予約語毎に記述する箇所がバラバラというのが非常にわかりにくいんですよね。
2,膨大な数のSTL
C++ の本などを読んでいると思うのですが・・・
modern C++ = STLの多用という感じがします。
かなりの数のSTLが存在していると思いますが、「STLを扱えない」というのがC++の難しい原因にもなっているような気がします。
C++はC言語の拡張として作られた言語なはずですよね?
しかし modern C++ はすでにC言語の面影がなく、全く別の言語化しているような気がするんですが・・・どうでしょうか?
std::stringはstd::cinと連携し入力されていくごとに要素がどんどん増えていくので、素晴らしい代物だとおもいます。
が、std::vectorやstd::unique_ptrなどのスマートポインタ・・・
自分はあまり使わないんですが、やはりC言語の生のポインタや配列の方が扱いやすいですね。
そもそもなんでわざわざ複雑なプログラミング言語にしたんだろう?という疑問がありますが・・・
面白そうなサイトを見つけたので載せておきます。
プログラミング言語の難しさはより遠くに飛ぶための翼である
正直、C++って面倒くさくないですか??
RustやNimなどの他の言語を使ったことがないので、自分には分かりませんが・・・
C++を使っている人はどのような理由でC++を使っているのでしょうか??
RustやNimなどではダメな理由があったら一緒に教えてください!!
また、C++の主にどの部分が難しいと言われているのか教えてください。
C++ はあまりに『熟練者に優しく』なってしまった
逆にイディオムがつかめれば、C++は余裕なんですかね?
ちなみに、自分がC/C++を使っている理由は・・・
「複雑なコードがかっこいいから!!」という単純な理由です。
「複雑なコード書ける俺様かっこいい〜〜」ということではなくて、C++がかっこいいと言う意味です。
[追記]
ふと思ったことなんですが・・・
C言語は「なにかと自分で作る系の言語」というイメージがあります。
C言語の拡張であるC++は、その考え方を引き継いでいるのではないですかね?
他の方からの回答をみると、「ライブラリ関連がしょぼい!」という意見が多いですが、これは、C++が「それくらい自分で作りなさいよ!」と言っているようにも聞こえなくもないんですが・・・
C++は機能が多彩でできることは、C言語よりも多いはずです。
「この多彩な機能を用いて、自分で作らなくてはならない」・・・これが難しい!と言われてる理由なのではないでしょうか??
家を作るのに、多彩な道具を与えてあげるから木を切るところから始めなさい!というイメージでしょうか??
あくまで自分の考えですが・・・
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。

回答6件
0
1, 記述の仕方がバラバラ(一貫性?がない)
Cを引っ張っている部分があることも否めませんが、一貫性はまだある方だと思います。どこにかかる修飾子なのかを把握すると自ずと慣れるかと。ただ、最近は型指定を後置にする言語(GoとかKotlin等)が多くなっており、それらに比べるとわかりにくいのはあると思います。JavaScriptはC-likeなのにTypeScriptの型指定が後置であるのもそんな理由だと思われます。
2,膨大な数のSTL
Java等の他言語に比べれば全然少ないし、むしろ足りないと思うぐらいです。STLだけではまだまだ不十分と考えて、boostを使っている人も少なくはないと思います(かなりの数がboostから標準に移って、昔よりは必要ではなくなってはいますが)。
私は理由は三つあると思います。
1, 言語仕様の膨大さ
CはC++の拡張です。Cの一部の機能を除いたほとんど全てを内包しているため、Cよりも巨大な言語仕様となっています。しかも、その拡張は野心的です。単にオブジェクト指向を追加したという話ではありません。テンプレートやオーバロード、C++11からは型推論やラムダ式等が追加され、肥大化される一方です。
2, パフォーマンスを追求するあまりの複雑さ
Javaはパフォーマンスを犠牲にしてでもGCを導入しました。C++にはスマートポインターがあるとは言っても完全なGCは標準でありません。なぜならGCではプログラマーがパフォーマンスの調整、つまり、どの段階でメモリを解放するのか、というのを完全にコントロールできないからです。
他にも参照はパフォーマンス面から非常に重要ですが、言語仕様を複雑にしています。C++03までは左辺値参照だけでしたが、C++11から右辺値参照が加わり、より高度にコントロールできるようになった結果、機能が増えた分だけ覚えることが増えたというのはあると思います。
3, 安全ではない
前の話にも繋がるのですが、これはCから引き継ぐ伝統だと思います。Cは容易にバッファーオーバーフローと言った未定義な動作になったります。C++も同様です。これは安全性よりもパフォーマンスを取っているからです。
たとえば配列の添字アクセスを考えてください。多くの安全な言語では例外を出して安全にプログラムを終了しようとします。しかしC/C++では何が起こるかわからないという未定義の動作になります。範囲外アクセスを検知し、例外等にしてしまうということは、添字が範囲内であるかどうかを調べる処理が入っていることになります。しかし、初めから範囲内であることがわかっている値であれば、その処理は無用の長物であり、パフォーマンスを下げる要因です。だからこそ、C/C++では範囲内であるかどうかの責任をプログラマーに持たせ、パフォーマンスを下げるようなロジックを組み込まなかったのです。
C++のSTLではちょっと便利になって、例えばstd::vector
にはat
とoperator[]
の二つの添字アクセスが用意されています。前者は範囲チェックを行う安全だけど遅い関数、後者は範囲チェックは行わない危険だけど速い関数、となっています。どちらを選ぶかはプログラマーの責任であり、C++はとにかく、プログラマーが意図しないところでパフォーマンスに影響するようなコードを含まないものを用意するようにしています。例えそれが、プログラマーのミスによって、プログラム全体を壊し、危険な脆弱性を産むものであってもです。
現代の新しい言語では「安全性を維持しながらパフォーマンスをいかに追求するのか」が主軸に置かれていると思います。これはたぶんJavaの成功が影響していると思います。JavaはC++に比べれば、パフォーマンスの面で越えることはできません。しかし、安全性という面ではJavaに軍配が上がり、JavaにはC++のような危険で動作未定義なコードを含めることができないようになっています。さらにJavaの悪い点、つまりはC/C++から引き継いでしまった良くないところを改善しようとする傾向が新しい言語で見られます。null安全や後置型指定と言ったところです。
安全性とパフォーマンスはトレードオフです。優れたプログラマーが書いたC/C++のプログラムに対して、安全性を考慮してしまった言語でのプログラムがパフォーマンスで優位に立つことはできないでしょう。しかし、マシンの性能向上により昔よりはパフォーマンス絶対主義はなくなりつつあるとは思っています。OSカーネルや各ライブラリ、インタプリンタなどのパフォーマンスが求められる基幹部分ではC/C++が残ると思いますが、その周りのロジック部分はより安全な言語に置き換わっていくのではないでしょうか。
投稿2018/04/21 22:26
総合スコア21741
0
ベストアンサー
Cはそもそも高級プログラミング言語というより高級アセンブラ
Cはアセンブラを楽に書きたい、という需要を満たすために設計されています。
ソフトウェアが複雑になってきてアセンブラ手書きではしんどい、という問題を解決するために、今までアセンブラでプログラミングしていた人が代わりに使うために作られました。
なので、アセンブラで可能なことはなるべく、というかほぼ全て、Cでも可能にしなければいけません。
そしてそれはアセンブラよりも楽にかけねばなりません。
結果、他の高級プログラミング言語では禁止されるような危険な記述が可能な言語になりました。
これは今までアセンブラでプログラミングしていた人たちにとっては大した問題ではなかったのですが、アセンブラを通らずにCでプログラミングを始めた人たちには大きな障害でしたし、ソフトウェアがさらに複雑になるとアセンブラから乗り換えたような人たちにとっても持て余すことになり、問題になるようになりました。
そんなCにC++はオブジェクト指向プログラミング用の機能を盛り込んでしまった
かつてオブジェクト指向がバズワードだった時代がありました。
ソフトウェアが複雑になってきてCで書くのも辛い、という問題の解決に、オブジェクト指向は銀の弾丸になり得ると期待されていて、C言語にオブジェクト指向プログラミングをしやすくする拡張を盛り込んで作られたのがC++です。
アセンブラからCに乗り換えてプログラムを書いている人たちに使ってもらうため、Cとの下位互換性は維持しなければなりません。
結果、他のオブジェクト指向プログラミング言語では禁止されるような危険な記述が可能な言語になりました。
C++はオブジェクト指向プログラミング言語としては結構古参
SmallTalkなどの先達はありましたが、オブジェクト指向プログラミングはまだ若い概念で当時の人類は妥当な言語設計を知りませんでした。
C++は良かれと思って多重継承、仮想継承などの仕様を盛り込んでこの世に地獄を顕現させました。人類にはそれらを適切に利用できる能力はなかったのです。
JavaやC#はC++先輩が踏んでくれた地雷原を避け、クラスの継承は単一継承のみ、インターフェースのみ多重継承を許す、という、より妥当な設計を選びました。
が、C++にはそれができませんでした。C++が設計された当時は楽観的で、人類はそれらを制御可能だと考えていたからです。
さらにテンプレートまで盛り込んでしまった
Cではプリプロセッサマクロを使った黒魔術のようなプログラミングが横行していたので、それを緩和すべく、かつAdaで実現されていたジェネリックプログラミングにも応用可能なようにテンプレート機能が追加されました。
Cのプリプロセッサマクロで痛い目にあった人が便利に使えるように用意された機能なので、C++で初めてプログラミングを始める人のことなどは全く考えていません。
JavaやC#のジェネリクスと違いC++のテンプレートはジェネリックプログラミング以外にも使える言語組み込みのマクロ機能にすぎないので、便利ですが複雑で、初学者にとっては出てくるコンパイルエラーの意味がわからず使用を断念するようなものになりました。
Cからの乗り換え組にとっては便利で安全なマクロでしたが、テンプレートが展開された結果の型名が文字列にして一万字を超えるようになると、彼らにとっても問題でした。
まとめ:C/C++が難しいのは既存の言語で既に仕事をしているプロフェッショナルを対象に設計されたから
アセンブラ→C→C++と数十年かけて順を追って体験していけば、なぜC/C++がこのような仕様なのか?が感覚的にも理解できるので実は特別難解な言語ではないと思います。
ですが、少しでもこの文脈を外れると、例えばFortranやCOBOLで業務をこなしていたプロフェッショナルでもアセンブラの経験がない場合、Cは非常に理解しづらい難解な言語に見えることでしょう。
そして、最近プログラミングを始めた人にとっては、こうした順を追った無理のない習得をするのは非現実的で、いきなり巨大なC++に挑むしかありません。
a = a + 1;
と書いても a += 1;
と書いても a++;
と書いても、全部
asm
1INC A 2STORE A, _a
というほぼ最小最速の同じアセンブリ(擬似コードです)に変換されうる現代の最適化コンパイラでは、Cの高級アセンブラ性というのはさして重要ではなくなっているのですが、C++は非常に巨大な言語になってしまっているので、Cでよく批判されるポインター・ポインタ演算子・アドレス演算子・配列変数周りの混乱した言語仕様をより安全で理解しやすいもの変えるとしても、それを他の言語機能を壊さずに実現するのは至難の業になっています。そのため最新のC++仕様でもC由来の評判の悪い言語仕様はそのままになっているわけです。
C/C++の反省点を反映したJava/C#/Goのような、より整理された後発言語が存在することで相対的に、C/C++は難しい、といわれるのでしょう。
NimやRustじゃだめなのか?
全然あり、C++の後継として非常に期待してます。が、現状でC++を置き換えられていないのは
- 既存の速度重視のソフトウェア、OS、デバイスドライバはみなC/C++で書かれている(採用するには新規プロジェクトを立ち上げるしか無い)
- まだ平均的な速度でC++に勝てていない
の二点が大きいのではないでしょうか。Nim/Rustの言語仕様に問題があるわけではなく。
投稿2018/04/22 18:34
編集2018/04/22 18:56総合スコア199
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/04/25 15:35

0
1, 記述の仕方がバラバラ(一貫性?がない)
単にキーワードをどこに書くかという問題なので、「難しさ」の本質的な理由ではないと思います。キーワードの意味(役割)を理解すれば、当然それをどこに書くべきかも理解できるでしょうし、覚えれば済むことは難しいとは言えません。
2,膨大な数のSTL
raccyさんも書かれていますが、C#やJavaに比べればできることは圧倒的に少ないですね。それに、数の問題は難しさの本質ではありません。前述のように覚えれば済むだけの話ですし、常にリファレンスを参照できるようにしておけば、すべてを覚える必要はありません。
正直、C++って面倒くさくないですか??
面倒くさいことも多々ありますね。ですのでC#も習得して状況に応じて使い分けています。
C++を使っている人はどのような理由でC++を使っているのでしょうか??
やはり使い慣れているというのが一番ですね。あとは、パフォーマンスです。メインはC#で作っていても、パフォーマンスが要求される部分はC++で書くということはよくやります。
難しさの理由は、すでにraccyさんの書かれていることに私も同意です。それに加えて「ハードルの高さ」という観点で、私は以下のように考えています。
- 標準機能が少ない
前述の通り、C++はC#やJavaと比べると標準でできることが非常に少ないのですが、それがハードルを押し上げている要因となっています。
C++で実用的なプログラムを作ろうとすると、外部ライブラリーに頼らざるを得ません。外部ライブラリーを使うには、言語の知識だけでなく開発環境全般の知識や、場合によってはOS寄りの知識(プログラム実行の仕組み)等も要求されますし、どんなライブラリーを使えばいいのかをリサーチするスキルも問われます。
初心者がプログラミング言語を勉強しようとするとき、モチベーションの維持がとても重要になります。絵を描いたり音を鳴らしたりといった「派手な演出」は、モチベーションアップに非常に効果的なことは身をもって体験しています。学習向けのプログラミング言語にその手の機能が豊富なのはそういう理由からでしょう。
ところが、C++では標準でそのようなことができません。簡単な図形を描く程度でも、何らかの外部ライブラリーを利用しなければできません。初心者にとっては相当ハードルが高いでしょう。私がプログラミング入門者にC/C++をお勧めしない理由はこれです。
- 文字列処理が煩雑
標準機能が少ないことにも関連してきますが、C/C++には「文字列型がない」という点で、他の言語に比べると文字列処理が煩雑になる傾向があります。string
系クラスは、文字列処理を幾分楽にはしてくれますが、あくまでも長さで管理する文字型データの配列にすぎないので、意味のあるテキスト処理をやろうとすると壁にぶち当たります(その手の質問も結構多いですよね)。
投稿2018/04/22 04:52
総合スコア5944
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。

0
C++が難しい理由を個人的にいくつか上げてみます。
まともな入門書が存在しない
C++11が出たことで別物と言っていいほどの変化を遂げたにもかかわらず、いまだにそれに十分対応した入門書は存在しません。
つまり結局規格書を読まないとわからないということになり、ハードルが高いです。
まあ江添亮さんが執筆中らしいので期待しましょう。
core言語/標準ライブラリが貧弱
欲しいものは大体C++標準化委員会にある、でも標準入りしない。つまり自分で書くか外部ライブラリに頼らないといけない。
もちろんこれはC++が安定性と互換性を極めて重視しているためです
C言語時代やC++03時代の負の遺産がある
歴史ある言語で、ある程度Cとの互換性もあるので、言語仕様が必要以上に複雑であったりします。
例えばいい加減2の補数の処理系を前提においてもいいだろうに未だにそれ以外の処理系をサポートしています(さすがにやめようぜって提案がC++標準化委員会に出て(P0907)、C言語標準化委員会にも意見伺いが出た(N2218))。
高速化できれば正義
C++はとにかく高速に動くことを目指すので、速度と安全性と利便性のバランスを取った結果他の言語より複雑になる傾向にあります。
GUIが標準にないどころかまともなGUIライブラリすらない
「標準ライブラリが貧弱」の亜種。
MVVMくらいできて当たり前な昨今、C++界隈にそんなものはありません。実はC++標準化委員会はGUIの標準化を将来のタスクリストに積んでいて、2Dグラフィックの標準化の後にやる予定なのですが、あと半世紀くらいかかるんじゃないですかねぇ(小並感
まあGUIはC#(XamarinがGTK#バックエンドに対応したからLinuxでも動く)ないしJavaScript(Electron)で書けってことなんでしょうかね。
マルチスレッド/非同期プログラミングに対するサポートがない
「標準ライブラリが貧弱」の亜種。
一応C++11でマルチスレッドへのcore言語側の対応と標準ライブラリのマルチスレッドへの対応とスレッドの標準化(pthreadをほぼそのままラップした感じ)が入った。
ところが他の言語だともうスレッドなんてものを意識することはそう多くなくって(ほんとか?)、async
/await
したりfuture/Promise/thenがあったりするのですがC++にはない。
C++17で入りかけたけどコケた。
ただまあC++20ないしC++23あたりで入りそうではある。やっとかよ。
ライブラリの管理が面倒
C++には処理系が数多く存在します。これが他の言語との大きな差で、そのためパッケージマネージャのようなライブラリ管理をやってくれるものが存在していません。
楽にするツールが無いわけではないですが(CMakeとか)、解決には至っていません。
Unicodeへの対応が不十分
C++でまともにUnicodeをportable扱うのは極めてむずかしい現状にあります。
かろうじてUTF-8,16,32にエンコードされることが保証された文字/文字列リテラルがC++11で(u8文字リテラルのみC++17)入りましたが、実質それだけです。
Unicodeに限ってすら文字コード変換ライブラリは標準化されておらず(C++11でcodecvtに大幅な拡張を入れて対応させたものの安全性の問題からC++17でdeprecatedになった)、外部ライブラリに頼らざるを得ません。
C++11で導入された正規表現ライブラリも例えばchar32_t
系向けには特殊化がなかったりして使い物にならない状態です。
標準入出力もやはり未対応でかつ、localeがぶっ壊れているので実行環境の文字コードについて知ることすらままなりません。
Undefined Behaviorとの戦い
C++er は“合法”だとか“違法”だとか言いたくて仕方がないけれど、結局どういう意味? それより適合・適格・○○動作・○○規則・診断不要いろいろの関係が謎
を読んでくれ、どう思うよ?(圧倒的死
投稿2018/04/22 08:15
編集2018/04/22 09:09総合スコア5852
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/04/22 09:17
2018/04/22 11:43

0
こんにちは。
C++を使っている人はどのような理由でC++を使っているのでしょうか??
マルチプラットフォーム対応言語としてはC言語に続く強者ですよ。
流石に8bitマイコンは厳しい場合が多いですが、16bit以上のマイコンの開発ツールにC++コンパイラがあることは多いです。ここいらまでサポートしている言語はC言語を除けばアセンブラくらいしかないのでは?
ただし、そのような小さなCPUも相手にしているため、逆にウィンドウ・システム等の高度な機能のサポートがありません。だからGUI開発ツールとしては残念ながら悲惨です。
C++が何故難しいか?
まず、難しいのは事実です。その分、高速な(軽い)プログラムを高生産性で開発できます。
Javaは JVMが必要ですから重いですし速いとは言えC++に比べると遅いです。しかし、学習が容易で高生産性です。
つまり、C++が難しいのは、高速なプログラムを高生産性で開発するためには、どうしても多くの知識が必要になるため、習得が難しくなるという要素が大きいと思います。
ただ、C言語時代からの上位互換性を維持しているため、歴史的な要因による難しさもあるのは事実と思います。修飾子等の問題はこれに属すると思います。互換性を捨てて構文を自由に設計すれば書くべき位置を分かりやすくすることは可能だろうと思います。
他にも難しい部分が多数あります。
Effective C++の著者のスコット・メイヤーズ氏はこの本の第3版で、C++はマルチパラダイムなプログラミング言語であると述べています。
C++は複数の言語の集合体と見なすべきだそうです。C言語、オブジェクト指向C++、テンプレートC++、STLの4つを上げています。
私は、それぞれのパラダイムでプログラミングの方法論が異なるため難しいのだと思います。私は更にマクロもあると思います。C/C++のマクロはプログラミング言語と呼ぶには中途半端ですが、それなりに強力です。そして、非常に奥深い使い方があり、それはたいへん難しいです。でも、超便利な時があります。
他に、以前「第1回目 なぜ今C++を学習するのか?」という記事を書いたことがあります。参考になるかも知れません。
投稿2018/04/22 05:30
総合スコア23274
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。

0
個人的な意見ですが
C++と一口で言ってもモダンC++とC++11未満で全く別物としか見えません。
さらに人によっては単なるbetter CとしてC++を扱う人もいます。
習熟度合いによって書くコードが全く別物になります。
その結果、ググって出たコードスニペットを取捨選択しなければいけません。
当然、取捨選択のためにはある程度のスキルを要求されるハードルの高い作業になります。
さらに、個人的な印象ですがC++の予約語は使い回しが多くググラビリティが悪いです。
習熟の容易さよりも、予約語を増やさずに互換性を維持する事を選択している印象があります。
またC++は多くの処理系が存在し
gccで動くコードがMSVCで動かないなんてのは昔はしょっちゅうありました。
まぁ規格化や第三勢力clangのおかげで大分減った印象ですが
C言語は高級マクロアセンブラとみなしても問題ありませんが
C++はそういう視点で見ると意味不明な事になるのも難しいところだと個人的に思います。
ラムダ式とか無名関数のポインタ貰えるんだろ?なんて思ってると
cpp
1#include <iostream> 2int main() 3{ 4 using namespace std::string_literals; 5 auto r = [](auto x, auto y){return x + y;}; 6 std::cout << r(2,3) << std::endl; // => 5 7 std::cout << r("a"s, "b"s) << std::endl; // => ab 8 return 0; 9}
上述と全く関係ないですが個人的に一番キライなのは
c
1printf("%08X", dw);
が
cpp
1std::cout << std::hex << std::uppercase << std::setw(8) << std::setfill('0') << dw;
になる事です。
投稿2018/04/23 02:25
総合スコア15149
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/04/21 22:44
2018/04/22 00:28
2018/04/22 06:24
2018/04/22 06:48
2018/04/22 06:51