C++相談室 part149
レス数が1000を超えています。これ以上書き込みはできません。
STLつかうと一気に実行ファイルサイズが10倍に?!
環境によるだろ。
俺はBorland-C++5.6.2に -D_RTLDLL オプションを指定して、極力
ランタイムを使用するようにして使っているが、例えばstd::vectorを
使っても使わない時と比べ10Kほどしか増えない
すげえ。ダイナミックリンクしといてファイルサイズが増えないとかいってるよ。この人。
C1010: プリコンパイル済みヘッダーの検索中に予期しない EOF を検出しました。
とかいうエラーが出るんだけどこれってどうすればいいの?
#include <stdafx.h>
後死ね。
言葉が悪いな。それで教えているつもりか。
まぁヒントぐらいにはなったな。
うむごくろう。
---- テンプレ ここまで ---- std::functionを使うなと言われたのは残念だが
newのときたまの遅さの可能性に警鐘を鳴らしたから勝利宣言しちゃおうかなっ
かなっ function・・・それだけか?
なんか組み込みにC++は向かないとまで
大きく出る理由として弱すぎね? あ、IDは気にしないでね
スレ主としての発言じゃないよ 乙
それ言ってたのは別の人だし過剰反応しすぎだろ
というかあのキッズを叩くと必ず単発煽りが出てくるのは恐らく同一人物だろうな
>>3
標準ヒープ使われてもいいなら使えばいいじゃん 君は誰?
組み込みにC++は向かないなんて思ってないなら
俺はそれ以上言うことないけど >標準ライブラリでもallocatorが指定できないものもあるんだよ
の人ではないよ
というか何がそんなに気に入らないのかね
組み込みに向かないと言ってた人はArduinoがどうこう言ってたろ
実際RAMが少ない環境ではかなり慎重に使わざるを得ないんだろ、知らんけど std::function は (呼び出しの型が一致さえすれば) どんな関数オブジェクト (または関数ポインタ)
でも格納できるというのは強いんだが、
実際にはコンパイル時に型が確定できる場合の方が多いと思うので
std::is_invocable_r で制約を付けた方が少し性能は良いと思う。
でもテンプレートって型引数ごとに実体化されちゃうから、
素朴に考えると引数をラムダ式で与えてたら呼び出しごとに実体化されることになっちゃうよな……。
(最適化で上手く統合されることもあるかもしれないけど。)
どちらを選んでもいいことばかりではないので、結局は場合によるとしか。 >>9
何がってそのままだよ
組み込みにC++は向かない、という意見に反対だ だから過剰反応しすぎだろ
functionの話してた人はゲームだろうが
反対するなら根拠を示せばいいし
少なくとも別の人の話は混同するな >>10
ラムダなら実体化っつっても毎回関数オブジェクト作るのと変わらんやろ IDなんかアテにならない
基本的に匿名掲示板なんだから
人違いはそう言えばいい
もっとも、それを信じるかどうかは別だが まさか前スレID:tDJaHP5Kじゃないだろうな? >>15
いや俺tDJaHP5Kだよ
過剰反応するなっていうおまえさんこそ
なんでそんなにとんがってるんだ?
色々勘ぐってしまうぞ >「後で」かw
>もう1000間近だし期限切らないでおけば時効だろってか?
こんなん書いてよく開き直れるな
側から見てて気分悪かったぞ
ちなみに俺は前スレnfQlnp9bな >>17
それは妥当だろ。
あの場面ではライブラリにアロケータを指定できない場合があると主張しながら例を示さない
のは議論の仕方がわかってないクズだし、そういう奴に遠慮してたら話が進まねーよ。
2ch って元々そういうところじゃん。 ああ、あいつか
元々newの話だったのに
mallocの話だってクレーム垂れてきたやつね は?頭湧いてんのか?
最終的に例出されたなら反論か謝罪かどっちかだろ
そこで逃げるという選択が取れる方がよっぽどクズだと思うがな 毎回荒れる原因作ってんのお前らだろ
さんざん煽って言い返せなくなったら別人に成り済まして単発煽り入れたり
マジ邪魔だわ それから俺は元々特定のレスや人物に異を唱えたわけではなく
流れ全体に対しておかしいと思ったことを言ったのが968だったぞ >>20
前スレで野党に喩えたのはそういうとこね。
事実関係は議論の前提だから、共有しないで先延ばしする理由はない。
カルトクイズに答えられない相手を見て悦に入るようなやつがクズでなくてなんなんだ。 だいたい喧嘩売ってきたのは978で
それまで平和的に話していた俺が
ひとこと言い返したのだけ取り上げて
気分悪いとかどういうバイアス持ってるんだよ >前スレで野党に喩えたのはそういうとこね。
それはどうでもいい、問題にもしてない
>カルトクイズに答えられない相手を見て悦に入るようなやつがクズでなくてなんなんだ。
悦に入ってたかどうかは本人に聞け
というか調べ方は出してくれてただろうが
お前も都合の悪いことからはとことん逃げるから、悪いが相手したくない >>24
>>978もそれまでのお前の態度と同程度には平和的だと思うが
どういうバイアス持ってるんだよ
悪いがもうキチガイキッズの相手はしたくない、絡んで悪かったな 自己弁護にしか見えねえ
どうやら勘ぐりは当たってたようだな アホか
俺が前スレ>>978本人だったらもっといじり倒してるわ MinGW のライブラリを見てたら std::function にも SSO が入ってる。
データメンバの総計が 16 バイト以下の関数オブジェクト (キャプチャした変数が少ないラムダ) なら new は呼ばれない。
※ string ではないのにこの最適化を SSO と呼んでいいものなのかどうかわからん
※ 16 バイトというのは環境によるだろうし、 SSO がないこともあるだろう
※ とはいえ、主要な実装ではだいたい有ることを期待できるのではなかろうか
間接参照にはなるから std::function はわずかにコスト高には違いないかもしれないけど、
ちょっとしたことに使う分には急激に実行コストが上がるというほどではない。
リソースの限られた組み込み環境だといずれにしても基本的なライブラリも
自前で用意せざるを得なかったりもするだろうし、
標準ライブラリをフルセットで使えるほどの環境ならみみっちくリソース消費量を抑える必要もないだろうから、
使いどころが適切であれば全体としてはあまり問題にならなさそうという感想。 (あくまでも個人の感想です!) 僕はArduinoこそC++パワーが必要と言ってるんですよ。 Arduinoは様々な亜種があるので、テンプレートでゴニョゴニョすると、何かいいことが起きるのではないか?
そんなことを議論してほしいわけですよ。
メモリーは2KBしかないけれども。 ちなみにエルチカとこんな感じ。
最大32256バイトのフラッシュメモリのうち、スケッチが932バイト(2%)を使っています。
最大2048バイトのRAMのうち、グローバル変数が9バイト(0%)を使っていて、ローカル変数で2039バイト使うことができます。 >>33-34
僕って誰や?
ランタイムのパワーが必要ないものはリソースの少ない環境用に積極的に活用するべきだとは思う。
Arduino についてはよう知らんけど、ドキュメントを見た感じだと type_traits のような
(実行時の) マシンパワーが要らないようなものまで除く必要はないやろという気持ちになる。 C++標準ライブラリはないけどテンプレートは使えます! 魔術師が活躍する舞台として最高だと思いますが。
なぜ参入してこないのか。 Running 5 test cases...
---------- std_algorithm__adjacent_find_1 ----------
std::vector<std::uint32_t>
size(): 104,857,600
std::adjacent_find: 66ms
---------- std_algorithm__is_sorted_1 ----------
std::vector<std::uint32_t>
size(): 104,857,600
std::is_sorted: 66ms
---------- std_algorithm__sort_1 ----------
std::vector<std::uint32_t>
size(): 1,048,576
std::sort: 119ms
---------- std_algorithm__unique_1 ----------
std::vector<std::uint32_t>
size(): 5,242,880
std::unique: 4ms
---------- std__vector__copy_1 ----------
std::vector<std::uint32_t>
size(): 104,857,600
copy assignment: 220ms
new std::uint32_t[]
size: 104,857,600
std::memmove: 55ms
*** No errors detected >>30
SSO = Small-string optimization Arduinoも一応newは使える。
使わないけど。 >>44
new を使わずに、かわりにどうすんの? 基本的にグローバル変数を駆使するしかないけど、結構強烈に最適化かかるので、意外と2KBで何でもできる。 プログラムが極端に小さいなら高度な抽象化をする甲斐がない。
抽象レイヤを挟むことで綺麗になるよりも複雑さが増すだけになりがち。
本当に使いまわす部品は綺麗に整理するに越したことは無いけど、
メモリ 2KB かそこらの環境ならベタ書きで十分でしょ。 (YAGNI 原則)
C++ が組み込みに向いていないとは言わないけど、
そのレベルで極端にリソースが制約されている状況では必要でもないと思う。 パソコンでは、恐れることなくnew使って良いと思うけど、static_vectorというのも自作した。 >>48
もちろん単にやるのが楽しい! というのも動機としてはありうるので趣味でやる分にはどんどんやったらいいと思うけど。 >>48
まあ確かに。
でも使いまわし出来ると便利だし、C++なら...やってくれる! いやいや、固定小数点とか組み込みだからこそのtemplateがふさわしい場面は結構あるよ >>49
どういう意味で static なの?
大きさが固定ってこと? ストレージ内蔵だけど内蔵キャパまでの可変長対応とかかね
知らんけど >>54
std::arrayにsize()をプラスした。 std::arrayは最初からsize()持ってるんだけどどういうこと? static_vectorってまんまboostにある
最大の長さが確定してるvectorで
メモリ確保は初期化時だけってやつ
それこそ組み込みやゲームでは有用
上の人のと同じかどうかは知らんが >>11
向くか向かないかなんて主観なんだからそこを力説してもしゃない
向くと思うなら自身の経験をもとに定性的に説明してみなはれ
あと組み込みってもピンキリだから
マイコンでモーターをPID制御するのと、
組み込みLinuxでメディアサーバー作るのとでは全く異なる世界
そこは区別しないと意味ある議論はできないね
後者は両論あるだろうけど前者はどうだろう?
そもそもモダンなc++で開発できる環境あるのかな? >>59
駄目ですか?
使えるなら使っていいンじゃなすか? YAGNI // "You ain't gonna need it" : 機能は実際に必要となるまでは追加しないのがよいとする。
Ajail 開発
↑こういう開発哲学の様なものは他にどんなものがありますか?
真逆の哲学でも構いません。 >>63
【KISS の原則 (英: KISS principle)】
「Keep it simple stupid.」(シンプルで愚鈍にする)、もしくは「Keep it simple, stupid.」
(シンプルにしておけ!この間抜け)、もしくは「Keep it short and simple.」(簡潔に単純にしておけ)
という内容の、1960年代の米国海軍において言われた、経験的な原理・原則の略語。
その意味するところは、設計の単純性(簡潔性)は成功への鍵だということと、不必要な複雑性は避けるべきだ、ということである。
【なし崩しの機能追加主義】
KISSの原則に反して、仕様が徐々に複雑化していくことは、ソフトウェア開発の世界でよくみられる。
これは、「なし崩しの機能追加主義」として知られる。
ソフトウェアが複雑になるにつれて、使い方を習得する時間が増えたり、操作に手間取ったり、どれが重要な機能なのか分からなくなったりする。
さらには、ハードウェアへの要求スペックが高くなったり製品価格が高くなったりもする。
しかし、大多数のユーザーが実際に使用する機能は、そのごく一部であったりする。
ユーザへの負担や開発コストを考えると、単純なソフトウェアの方がユーザフレンドリかつ生産性が高い可能性がある。 KISSの原則、俺は正しいと思う
オーバースペックなものを作っても、その「オーバー」な部分が
あとで必要になったとき不十分なんてことが起きやすいからな
案件の「今」を最大限に最適化するのは義務と言ってよい努力だし
なし崩しの法則は、変更要求に対する不適切な対応が積み重なって起きることだ
既存のソースコードや回路図の微修正で済ませようとするあまり
それまでの反省を踏まえてきれいにリメイクすれば解消する問題が
ずっと影を落とし続ける現象はそこいら中あふれかえっている 車輪の再発明なんて例えをよく見かけるが
じゃあ今の車輪はまだ木で出来ていたり
パンクしやすいチューブタイヤだったりするのか
進歩の原動力たる、たゆまぬ努力に対する
アイディアキラーは見逃しちゃダメだ >>63
契約プログラミングとかもそうかな?
C++20 にサポートが入る予定だったが、次以降に延期された。
まあ言語としてのサポートがあろうとなかろうと関数が機能するための前提条件
を意識したり明記したりするのは良いことだと思う。
文芸的プログラミングという考え方もある。
説明文とコードを分離せずに書くようなもの。
提案者 (クヌース) が考えていたのは文章説明を中心にする考え方で
コードの方が従属するようなものだけれど、
コメントとしてドキュメントを書くようなものなら doxygen や Javadoc はよく使われているね。
コードを書いているときはちゃんと把握できているからドキュメントを後回しにしがちだし、
コードがドキュメントであるようなものが理想とか言う人もいるんだけど、
数日前に書いたものさえ割と忘れるのが人間なので文書で残すのは大事だと思う。
テスト駆動開発も割とメジャーかもしれない。
仕様をテストコードとして書いて、それを満たすように実装を進める手法。
テストできるように作らなければならないという点で実装に制約が付くのが嫌われがち
ではあるようだけど、仕事でやる開発なら客にアピールしやすい気がするなぁ。 doxygenで作られたドキュメントあんま役に立たないよ
特にテンプレートリッチなコードだと余計なものや個々の実体化までドキュメントに入る
まぁそれを避ける方法が無いわけではないしdoxygen用にコメントをきっちり書くのは良いことなんだけど >>67
車輪の再発明っていうのは、車輪を知らないで「発明」することだよ。
既に普及しているものを知らず、学ばずに思いつきでやって既出の失敗を繰り返す愚かさを言ったもので、
学んだ上であらためて自分で作ることや改良することを否定してはいない。 >>69
個別のツールについては私は良く知らないんだ。
ここではドキュメントとコードを同時進行で作るという考え方の話。 >>70
ところが、「車輪の際発明」と言って批判する人こそが、全く試しもせずに妄想していることも多い。
この言葉をインド人が言っているのを見て、だから後進国のままなんだな、と思った。 車輪を題材にした慣用句であり、世界中で使われている。
「広く受け入れられ確立されている技術や解決法を知らずに(または意図的に無視して)、
同様のものを再び一から作ること」
を意味する。 MS officeのフリーの互換製品を作ることは違う >>70
同じことだ
学生や新米が何か思いついて実験してみてるところへ
身も蓋もないことを言ってやる気なくさせる老害は進歩の邪魔だ パーキンソンの凡俗法則
どうでもいい話題ほど紛糾する
車輪の再発明がどうとか
gotoがどうとか >>76
俺、サラリーマンやってた頃は
手が空いたとき色々実験してたよ
向上心のないやつを蛇蝎のごとく嫌う上司だったし >>75
それは思いつきとは言ってもまだ学びの段階の中の話でしょ。
学ぶためにやってるのなら別にいいよ。
学習段階によって当然知っているべきことを学べてないなら軌道修正はするべきだが。
程度問題とか状況というものもある。
上にあげたような方法論がある程度の確立はしているとは言っても、
業務に取り込むにあたっては色々と試行錯誤はあるもんだしな。
>>76
仕事に必要な学習なら業務時間中にやるべきだし、
そのための時間が与えられないなら会社が学ぶなという方針なんだろう。 学ぶ?
毎回プロジェクト初めに同じものを同じだけ時間かけて作り直すのが学習?
前のを使えよ プロジェクトが始まったらニコニコ顔で同じ作業を同じように繰り返して
夜になったら必要もないのに残業してふーってニコニコして仕事
ある程度満足したら帰る
そしてプロジェクト終了間際には死んだような顔をしてこんなの間に合うわけないとか言い出す
車輪の再発明にかけた時間をそこに回せよと プロジェクト始まったころにSEが間に合って仕様書も来てないのに意味もなく残業してるやつら
何をしてるのかと思うと勉強しようと思ってとか言って全然関係ないことをしてる
家でやれよバカ
死ね給料泥棒 × SEが間に合って
○ SEが間に合っていなくて 業務でやるならそのあたりのバランスを決めるのは管理者の裁量次第だろ。 >>80
自動化できるものは自動化すべきだね
コピー一発で済むものとジェネレータがいるのとある
俺、ジェネレータ作るの楽しくて好きだ 学習に時間を使ったのに同じように失敗する馬鹿。
糞シンタックスを覚えることに時間かけるんじゃなくて
普通にメトリック取ったりテストコード書けって話なんだが、理解できないのだろう。 > 俺、ジェネレータ作るの楽しくて好きだ
この場合のジェネレータって一体何? 同じものを1度作っても2度目作れない
同じくらい時間はかかっても2度目作ると3度目は作れるようになっている
それは無駄ではないと思っている 海外の掲示板で「車輪の再発明」することを馬鹿にしていたもう一人の人は、哲学科出身で、宗教関連の発言ばかりしてる人だった。
理系ですらない。
自分では作らずに口だけ達者な人だった事が追跡できた。 全然関係ないことを持ち出して
自分と意見の違う人を馬鹿にできたつもりになってるやつは
論理的な思考が極度に苦手な、理系文系以前に無学なやつだ >>92は車輪の際発明を馬鹿にする人が一人しかいないという命題に対する反例
としては全く正しい >>82
プロジェクトを効率よく回した方が良い
あと残業を作業者自身の裁量に任せるのはシステムがNG
裁量労働は結果責任を果たせば会社が回るクラスの仕事をしているハイクラスな奴用
SEが必要なときに前の仕事が終わっていないかもしれないからロックしておくというケースで
前の仕事が終わったSEが次の仕事のスタートまでの間、
定時内に会社で独学するのは別段怒るほどのことではない ここ老害のおっさんばっかりだからな
ところ構わず自分の言いたいことを言いまくる
はいおっさん続きどうぞ 他人が自分と違う意見を持つ事実を受け入れられず拒否反応するだけな幼児性は無学のさらに以前の問題だ 「車輪の再発明」という言葉は、加工貿易しか生きる道は無い日本を必ず衰退させる。 車輪の再発明すら出来ない無能にはこの上なく都合のいい言葉だなw >>101
実際、最近では同じ事を作ることすら出来なくなっている。 教育や訓練でやっていることは「車輪の再発明」だよ。 >>103
というか、ホリエモンロケットもアポロのエンジンを真似ているだけとされるのに
何度も墜落したり、三菱のジェット機(旧MRJ)もボーイングなどとほぼ同じような
ものだけど、納期を大幅に延期しまくっても完成できてないように、同じものを
作るということですら簡単では無い事がある。
逆に言えば、ソフトウェアでも売り物と似たようなものをフルスクラッチで作れたと言うことはなかなかの技術力があったということ。 >>79
学生と新米と言ったがそうでない者が
既存のものを知った上で再考することだってある
最初に出した例えで、木でできた車輪や
チューブタイヤがあるのを知った上で
さらに進化できないかなんて話は珍しくもない
そこへ木の車輪があるのに何をしてやがると
突っかかるのをやめるべきだと言っているんだ
人がどんな目的で実験しているのかを
勝手に決めつけている点も問題だ >>105
学んだうえで改良しろってのは最初から言ってることで、そこは否定してないじゃん。
何言ってんの?
そもそも >>75 で出てきた老害ってのはどっから湧いて出てきたんだよ。
お前が文句付けてるのはお前が言い始めた老害に対してであって俺じゃないだろ。 マ板でやれって言われてるのはそういうとこだよ。
困った老害がいるのならそりゃ大変ですねとは思うが、
C++ 板で言っても知らんがな。 美術科の大学生が200万円自腹かけて作った卒業制作品に買い手がつかないのも「車輪の再発明」ゆえの想定内。 というかはちみつはあくまで趣味グラマなのにプロでやってる人の事情に知った風な口きいて首突っ込むから
それに反論すると必ず話がややこしくなる
スルー推奨 プロでも環境によって全然違うのに、一律に使えないと断定するから反発されているってのが目立つと
組み込みやコンシューマのゲームに限定しても使える、使えないは変わるのだから まあc++の思想としてどんな状況でも使えるユニバーサルな言語を目指してるってのは
あるからな。真に受けて馬鹿が狂信するってのはある意味では不思議じゃない。 >>106
おまえさんは何か思いついたとき
その思いつきと同様の先人の業績をいちいち調べ上げるのか
俺はそんな悠長なことをするより即やってみたい
調べるのはそのあとだ
木の車輪だって自分でやってみなきゃ気持ち悪いし
アンプは量販店で買えても回路組んでみたい
パンピーとハッカーの違いはそこだろ 「板違い」というが、議論と言うのは多岐に渡って派生しても良いもので、それでスレッドが機能不全になってしまうのは、コメントがツリー状にできない2ch/5chそのものの問題点。 >>115
>おまえさんは何か思いついたとき
>その思いつきと同様の先人の業績をいちいち調べ上げるのか
ここ、気持ち分かる。
なんでもやってみる前にすぐに調べようとする弊害と言うものが指摘されている。
調べずに自分の頭でやってみることが脳を鍛える。 >>115
車輪の再発明という言葉が出たからその意味に当てはまらない場合だと思うと私は言ってるだけで、賛否の意見は無いよ。
所詮は俺は趣味人だもの。 エンジンやモーターとかなら他社のものを買ってきて分解すれば学べるが、
プログラムの場合、自分で小さなものから作った方が学べることが多い。
既に出来ているものは複雑すぎて本質を学ぶのは難しいし。
それにFOSSはなぜかサイズが大きくて無駄が大きいことが多い。 stdにあって条件的にそれで十分なのに、わざわざ劣化版作る奴には車輪の云々って言葉が当てはまる
大体そう言うのバグっているし Arduinoやってみた感じでは、組み込みにもC++は有効だな。 static_vectorはダブル・アレイのリロケートに使った。 ダブル・アレイで一番効果あったのは、解放されたノードをリンクリストにつなげるときに、整列させるのが一番効果あった。
ダブルアレイは挿入でさえノードの解放が発生するので、確保・解放を壮絶に繰り返す。
この時、リストの末尾に追加するなら、何も計算が必要ない。
整列させるなら検索が必要になる。
ところが、整列させた方が挿入も検索も早くなるという結果に。
すべてキャッシュだと思う。 ちなみにヒープはstd::vectorの上に作った。
std::vector単体のベンチとると遅いんだけど、実用上はそんなに遅くない。
そういうわけで、最近はstd::vector上にヒープ作るの流行ってる。 キャッシュに乗るか乗らないか、それが人生のすべてだと思う。 ツリーも試作してみたんだけど、std::vectorの上にヒープ作った。
ヒープの何が良いかって、そのままserializeできるとこだと思う。 今はwindows案件ばかりだけど
数年前くらいまではlinuxばかりだった
LL以外はほぼc++のみ 車輪の再発明は結果的にそうなるというものであって
そういう現象なのであって
良いも悪いも善も悪も
ないお 真に手間をかけたくなくて時間が惜しい当事者ならアルゴリズム辞典ぐら普通当たるし
そうではなくて他者とか部下が車輪の再発明に時間を浪費するのが我慢ならないのなら
正解を提示してやるべきだろうJK
マ板でやれ、 文明を0からやり直すとか
糸車と水車でコンピューターを作ることとか
いろいろ >>135
何かをやりかけた人をやめさせて、それ以上発展させないようにするために使われる言葉かもしれない。 >>137
もう一つは、既存のプログラムのステークホルダーが、新しく作らせずに既にあるものを使わせようとするための口実や詭弁かも。 この言葉、NPO団体勤務の人が使っているのを見た。
偉そうなこと行ってるけど、実績も学歴もたいしたこと無い。 とある掲示板を見ていたが、この言葉は「その人の中では正しい」だけだと思った。
彼によれば、「自分で書くより既存のものを使ったほうが、大抵の場合は優秀だから」
ということであるが、それは彼の場合であって、自分で書いた方が優秀なものが出来上がる確率が高い人には当てはまらない。
要はIQが人並みを遥かに超えた人と、人並みの人の場合では異なってくる。 メンデルの遺伝の法則とか車輪の再発明がもう何度目だナウシカ状態、 そもそも自分が優秀だと勘違いしてるヤツだからこそ
糞の山を量産して満足げなんであって
自分の愚かさを理解できてるやつは
糞の山作りかけてる時にそれに気付いて引き返す なんで既にあるものをそんなにもう一回作りたがるの?
めんどくせえじゃん わかったC++の話にもどろう
まずはC++で効率のよいコレクションクラスの実装について・・ >>144
ねえ、プログラマなんて既に数え切れないほどいるのに
なんで自分もなりたがるんだろうね
他の職業にもすべて当てはまるね
無職がいいの? あ、死ねって意味じゃないよ。死者の数はもっと多いのでそっちの方がもっと不要。 「自分の愚かさを理解できてるやつ」
これはみんなが同じ力量であることを前提にしていて、こういうところが嫌だ。 天狗になるのも、どうせ馬鹿だからと居直るのも
正反対のようで共通点がある この分野はレベルの差が大きいので、一般レベルからは有り得なくても天狗とは限らない。 gotoの次は車輪か。
テンプレに付け加えていけよ。
記録することで無駄な議論を減らすってあたりまえのことができてないから
馬鹿なことを何回でも繰り返すんだよ。
安倍政権といっしょでさ。 gotoの話はみんな通る道なんだよ
後輩が議論するのを邪魔してやるな >>154
おまえみたいな馬鹿にうんざりしてるとこだよ。。
馬鹿はゴキブリみたいなもんだからな。 std::vectorはPODだと最終的にmemmoveが呼ばれるのにmemmoveよりだいぶ遅い。
それと何故memomoveなのかよくわからない。 ここは趣味でプログラミングやってるギーク多そうだけど
まともなC++人材がいないせいで進歩がウン十年遅れてる業界がかなりあるから
どうかそういうことに飛び込んでいってくれないかな?
あ、給料はたぶんクソ安いけど日本への貢献と思って >>159
その気持ち分かるよ
>>152みたいな隙あらばアベガーゴキブリにはいい加減ウンザリだよな 実際に馬鹿に馬鹿って言わないと安倍政権みたいな状態になるってのが今の政治に対する教訓だわな。。
ここも同じか。 >>164
誰に向かって言っているのかは知らないがお前自身に言い聞かせているんだろうな ---------- std__pair__construct_1 ----------
std::pair<std::uint32_t, std::uint32_t>[]
size(): 104,857,600
construct: 0ms
for (std::uint32_t i = 0; i < n; ++i) a1[i].second = i; 30ms
struct twice { std::uint32_t i1, i2; }[]
size: 104,857,600
construct: 0ms
for (std::uint32_t i = 0; i < n; ++i) a2[i].i2 = i; 0ms 一億個書き込んで0msなのは最適化で消えるんですかね? 今度は最適化で消えないように末尾をIOしたら、なぜかstd::pairのほうが速くなった。
std::pair<std::uint32_t, std::uint32_t>[]
size(): 10,485,760
construct: 0ms
for (std::uint32_t i = 0; i < n; ++i) a1[i].second = i; 20ms
1[n - 1].secondt10,485,759
struct twice { std::uint32_t i1, i2; }[]
size: 10,485,760
construct: 0ms
for (std::uint32_t i = 0; i < n; ++i) a2[i].i2 = i; 42ms
a2[n - 1].i2 10,485,759 最適化で変数が消されないようにするおまじないってないんですかね? 当然と言えば当然だけど消されないようにしたらスタックオーバフローするので、グローバル変数に追い出したら、構築時間を測る方法が無くなった。 nをsizeと書いておいた方が後でわかりやすいのかな。 大きなスタックをとる方法かms以下を測る方法みつけないと測れない。 おまえが頭悪いのは十分わかったから、もう書き込むな ちなみにグローバル変数で一億個確保したら今度はClangがギブアップした。
1000万個ならClangでもいけた。 std::vectorは初期化子リストによる構築が出来るんだけど、そこでもオーバーフローしたような気がする。
でも、元ネタは別にスタックに入れなくてもどこかにあるはずなので、なぜそうなるのかよくわからなかった。 そもそもコードを書いた時点でされるであろう最適化を
まったく予想できていない
もうこの時点で脳味噌がコンパイラの知能より劣ってるのが確定
これすらわからんから延々と馬鹿な実験を続ける バカな実験は勝手にやっててくれて構わないが、いちいちここに書き込むのはやめて欲しい。バカなことでも呟いていれば誰かが正しいことを教えてくれるだろうというスタイルなのだろうか? >>185
ハイそういうスタイルです。
C++コミュニティは親切なので誰かが「ちげーだろバカ」と教えてくれます。 他に気付いたことは。
gotoはかなり使い道がある。
newは意外と速い。
std::vectorはコンテントによって最適化してくれるので基盤としてなかなか良い。 メモリー分断化は全く問題にもならなかった。
そんなに心配ならOSもJavaで書くしかない。 >>186-187
マイクロベンチマークは特性を見極めるのに使うべきで、
その特性が用途に適合するかどうかという視点で見ないと意味ない。
当たり前だがあらゆる意味で最強ってことはそうそうあることではなくて、
良い部分もあれば悪い部分もある。
普段はかなり良質な機能でも、その悪い部分を使うような用途だったら
使い物にならないかもしれない。
「間違い」っていうのは目的にマッチしないってことなんだよ。
目的・用途が示されないベンチマークがダラダラ流れててもそこに間違いもクソもない。
指摘を期待するなら指摘できるような形に整理して欲しい。
C++ スレだから言語仕様に反することは (目的にかかわらず) 間違いと言うかもしれんけど、
言語仕様で未定義のことでもやむをえずやることは C++ ではあることだしな。 まずbenchmarkをとる方法がわかってないから。 ベンチマーク取ること自体が目的なのはプロセッサベンダーとパソコンオタクだけ
まず要件があって、それを満たすことの判定のために設計するのがベンチマークだ >>188
そもそも、Javaの方がメモリー効率が悪い。
現実的にはGarbage Collectionはメモリーの節約にはならない。 >>194
実装と実装の比較をする場合もあれば
試作と要求スペックの比較をする場合もあるね >>194
比較のために取ってるんだよ。
入力がランダムな場合と、整列されてる場合とか。
生ポインタとstd::vectorとか。
だいたいの傾向が見たい。 でお前は何を相談したいわけ?
中身のない活動報告しないくていいから >>198
まあそういわれればそうかも。
スイマセンでした。 Twitter とか Qiita とかで書いといて 車輪どころか分裂勘違い君を再生産するのがC+++じゃねえか だから悪かったって。
そんな怒らなくたっていいやん。 質問ですが「〜の最大値」って英語で書くと「Maximum value of 〜」だと思うのですが、
<limits.h>のINT_MAXのようにMAXimumを後置にする書き方もそこそこ見かけます
〜MAXという名前と、
MAX〜という名前では英語圏の人的にはどっちが自然? 〜MAXはINT_MAXみたいな不変の固定値
max〜はある配列の最大要素みたいなその場で求めた最大値の変数名に使いたくなる
日本人だからこれがネイティブな感覚かどうかは知らん std::numeric_limits<int>::max() も語順は int, max だね >>206
C++ の文法的な制約による順序だから命名規則としての語順とは別物だと思うけど、
こういう風に文法で縛ってくれる形での記法だと (英語的な) 自然さに悩まなくて良いよね。 int というカテゴリの中に max があるべきか
max というカテゴリの中に int があるほうが合理的か
どっちだと思う?
俺は後者は、あまりにも漠然とした概念のカテゴリ名で探す気が失せそうに思う
205が指摘しているように同じ英単語でもどういう意味で使っているのか解釈に幅がありすぎ 無理にクラスにせず関数にしろってのは
「無理な分類はするな」っていうC++の理念じゃないの >>211
西洋圏の人の場合、例えばハンガリアン記法では、人の人数は、numPerson、
CPersonへのポインタは、pPerson、Textが0終端文字列であることを表すためには、
pszTextとする。
これらは、number of persons, pointer to a person,
pointer to string with zero end for Text (???)
などに対応している。最後のはよく分からない。
ならば、maxPerson のようなつけ方もあってよいはず。しかし、
でも、PERSON_MAX というような命名法もある。
他の変数と並べたような時に、どちらが整理し易いかなどでそのプログラマが判断しているのだと思われる。
結論から言えば、オールマイティーな命名法は無い。 システムハンガリアンはハンガリー人が作ったんじゃないぞ
アメリカ人がtypeという英単語の意味を誤解して始めた今日では物笑いの種になってるやつだ 英語圏にもアホはいるんだよ
マイクロ波とガンマ線が区別できなくてヌークだヌークだ言ってる田舎者のせいで
スマホ恐怖症になってる情弱が後を絶たない 英語ができる=かしこい
と日本人は思いがちだ
日本では外国語はかしこくないと習得が難しいが話し相手の外国人は普通のやつが多い
知能指数が20くらいは違ってるはずだから会話内容は絶対かみ合っていない
でも話している日本人は交流できていると思って喜んでいる
日本人の言う知能と外国人の知能も多分かみ合っていないんだろう >>63
少し話がずれるが、OOPには、「SOLID」原則なるものも有る。 SOLIDとoopはそんなに関係はないけどな。
oopに神経使うくらいならSOLIDやTDDの理解に時間をかけた方が近道だわ。 std::mapの値を取得するときに、右辺値で取得するより.at使う方が例外処理がある分遅いですか? そんなことも聞かないとわからない奴は安全な方使っとけ 富豪的プログラミングは厨三病の証かw
客の表情を一切気にしないオナニー野郎 客の表情を気にすればこそ安全性・堅牢性が最重視される。速度は二の次。 >>227
はぁ?そんなわけないだろ。
すでに安全性・堅牢性が確保(割り切りも含む)されているから、速度改善に注力できているだけだぞ。 安全性と堅牢性を要件に必要としない案件って何だろう… >>228
とにかく時間を節約したいから速いソフトが欲しいってことは多々ある
正しく使う限り正しく動くなら問題ないのでそれ以上の安全性は不要
他者から攻撃されることはないから堅牢性も不要
そういう状況普通にある
身近な例ならお前だって使い捨てのスクリプトに過剰な引数チェックとかしないだろ? >>231
納品したりパッケージ開発するだけが
ソフト開発の仕事じゃないってことだよ レコメンド関係は安全性なんかよりも効率重視だがな。
スマホゲーなんかもすぐ落ちるじゃん。
それでも遅くてカクカクするよりかは喜ばれるわけだ。 お高いシミュレーションソフトなんてちょっと入力ファイルや引数間違えただけで落ちるけど おやおや?
例として挙げられるのは、スマホゲームとシミュレーションだけですか? >>226
おまえさんは速度を重視するのに安全性と堅牢性を犠牲にするのか?
ずいぶん甘い考えしてるな >>235
ユーザー入力は厳格な検査を経て内部ロジックに渡すのが鉄則だろ
そういうのをサボる口実に速度を持ち出すクズはプロジェクトから叩き出せ >>239
プロジェクトって言うか売り物買っただけなんだが
GUIでもメッシュ細かすぎると描画重すぎて実質ハング状態になったり だから堅牢性よか速さが欲しい
数十億ポリゴン使うなら速さを優先しないとそのソフトは実用じゃない
描画されないとそのソフトが存在する価値がないからな 自分はソフト屋でございハードは全くわかりません
なやつが詰むケースだな 絶対安全で一日かかるプログラムよりも
3回に一回は落ちるが10分で終わるプログラムのが価値のある場面は多いよ。
まあ場面によるしトレードオフの話だからどっちでもいいのだが
意固地になるのは違うだろうという話。 「落ちる」ことなく一見正常終了のように振る舞い誤った結果を出力するゴミプログラムの価値はゼロ コンパイラの最適化に期待するコードを書くよりも、処理するデータ量を減らす努力をしたほうがいい。 「ほうがいい」 「よりまし」と言って下位に位置づけたものを不要という暴論 3回に1回落ちるようなクソプログラムが配列末端や不正ポインタからゴミを読んで計算結果に混入させてないと誰が保証してくれるの?
そんなゴミクズを混入して一生懸命計算したゴミ結果に何の価値があるの?
何でもいいからそれっぽい数字が出てりゃいいの?だったら/dev/urandomから適当に数字吐くスクリプトで十分だな
お前のクソプログラムの価値はその程度だ >>231
ハードのおまけのサンプルソフトとか大学の研究室用のツールとか
使う相手もそういうのが理解できてることが前提だし契約もそういう不具合についても規定する >>247
> 3回に1回落ちるようなクソプログラムが配列末端や不正ポインタからゴミを読んで計算結果に混入させてないと誰が保証してくれるの?
絶対安全で一日かかるプログラムの出力も誰も保証してくれないけどねw だいたい新バージョンってのは新機能だったり高速化だったりが売りになっている。
旧バージョンでも動いてたシミュレーションはベンダーでもユーザーでも同一の結果が出るか確認するからバグはあまり混入しない
ある程度ユーザー側で検証が済んでからユーザーは移行する。
新機能はパラメータがちょっと違うだけでバグったりするから安定するまで結構な頻度で更新版が出る。 自分の利用する範囲で正常系入力にたいして妥当な結果さえ出ていれば、それ以外でどんなに酷いバグが混入していようがユーザーはあまり気にしない
ユーザーによってはバグフィックス版への移行に対しても慎重なところも良くある。 わかった、C++の話にもどろう・・
まずはC++で堅牢なメモリリークのないポインタ管理をすべきか
それとも速度優先である程度のリスクを負うコードを書くほうがいいかについて つか、速度必要なところではポインタに変換して演算するけど所有権管理はスマポでやるだろ >>254
ナマポよりスマポを使えって言いたいんだろ
他人に何を自分のスキルに合わせて話せと?
前提が違うから話しようがないんだが >>254
ケースバイケース。以上。
後はバカが極論語るだけの世界だ。 >>254
しれっとメモリリークをなくすと必ず速度が犠牲になるという前提になってるけど、
そんなことは無いので無意味な話題。 バカが極論語るというよりも
素人が空想語るって感じだけどいつもこのスレってw ファイルのバイナリ読み込みをしています。
下記のように最初の2バイトが単位レコードのバイト数を表しているとき、
単位レコード全体を表示しようとしているのですが、うまくいきません。
どうすれば表示できますか?
00 08 FF FF FF FF FF FF
-----
|
+----------------- レコードのバイト数
typedef unsigned char BYTE;
// dataはすでにファイルからバイナリデータとして読み込んでいるもの
int rec_size = (data[0] << 8 | data[0+1]);
BYTE* temp;
temp = (unsigned char*)malloc(sizeof(BYTE)*rec_size+1); // 改行を含めたメモリ確保をしているつもり
memcpy(temp, 0, (size_t)sizeof(BYTE)*rec_size);
temp[sizeof(BYTE)*rec_size] = "0A"; // 改行コード挿入しているつもり
printf("AAAAA %s\n", *temp); //レコード単位を表示
exit(EXIT_FAILURE); memcpy(temp, 0, (size_t)sizeof(BYTE)*rec_size); まずそもそもunsigned charは文字列ではないから%sではだめですね。
どうすれば16進数表示が出来ますか? あるいはこれか
printf("AAAAA %s\n", *temp); //レコード単位を表示 >>262
これコンパイルエラーだろ
実際のコードを張り付けろ あまりにぶっ壊れすぎて何がしたいのか分からん
レコードってのは長さの2byteを含む?
長さ以外は文字コードでそれを文字列として表示したい?
それともバイナリで16進表示したい? %xにしたらコンパイル通りました。が、出力結果は「0」になりました。。
typedef unsigned char BYTE;
// dataはすでにファイルからバイナリデータとして読み込んでいるもの
int rec_size = (data[0] << 8 | data[0+1]);
BYTE* temp;
temp = (unsigned char*)malloc(sizeof(BYTE)*rec_size);
memcpy(temp, 0, (size_t)sizeof(BYTE)*rec_size);
printf("AAAAA %x\n", *temp); 下記バイナリデータがあったときに、頭の2バイトが8なので、8バイトをtempに格納し16進数で表示したいです。
連続したバイナリデータで今読み込んでいるレコード単位がどの部分を読み込んでいるのかを確認しようとしています。
data = 0x0008AABBCCDDEEFF 実際のdataには下記のようにバイナリファイルの全データを読み込んでいるので、そのうちの一区切りのレコードを表示したいです。
data = 0x0008AABBCCDDEEFF0004AABB0005AABBCC
よく考えたらtempにmemcpyせずにdataから直接表示できればそれでもいい気がしてきました。 貼ってるコードがデタラメすぎて意味不明だからとりあえずやりたそうなことをベタ書きするぞ
これで合ってるか?これをカッコよく書きたいって話?
for(int i=0; i<rec_size; ++i){
printf("%x\n", data[2+i]);
}
printf("\n"); >>269
そのイメージです。
0008から表示させたいので printf("%x\n", data[i]); ですね。
これをスマートに表示できますか? for(size_t i=0,l=0;i<全体の長さ;i+=l){
l=data[i]<<8 + data[i+1];
for(size_t j=0;j<l;++j) {
printf("%02.2X ",data[i+j]);
}
printf("¥n");
} l=... + ...
じゃなく... | ... ありがとうございます。
bit演算させて%02Xで表示させるんですね。
%02.2X は %02X になりますか? うまく表示できました!
今勉強中で助かりました。
ありがとうございました。 また行き詰ったので教えてください。。
http://codepad.org/YzpjTJeN
上記コードで3つわからないことがあります。
(1)itemsリストを作り、構造体のITEM_A, ITEM_B, を追加していく
そもそも構造体の中身が違うものを一つのリストに追加できるのか不明。
(2) itemsに動的にリスト追加
(3) itemsのリストをfor()で1要素づつ表示させる
※(1)(2)がわかれば(3)は自分でもわかるとは思いますが。
どのように書けばよいかわかりますでしょうか? itemの数が膨大にあり速度がほしいので、リストに追加するところは先に個数を確保したいのですが、0xEEまで精査しないと何itemあるのかわからないので、vectorで動的追加しかないかなと思っています。
emplace_backだとpush_backよりは多少速い? >>277
ITEM_AとITEM_Bってtypeの値が違うだけで同じ構造体で良いような気がするが… vector使うかどうかよりも、毎回raw領域確保するほうがよっぽど問題と思うよ。
dataは何処かにおいておいて、rawにコピーせずに場所だけ指し示すようにしたほうがいい。
いずれにしても、計測なき最適化は害悪。 新型肺炎COVID-19は人工的に作られたともそうでないとも言われている。
プログラマの意図しないバグを含むプログラムを公開してしまったとしたら、そのプログラムは人工的ではないと言えるのか? このプログラムの最終目的はなんなんだろう
作ったitemsリストは表示するだけじゃなくて後で別の目的に利用するのかな std::stringをkeyにして作成されたstd::mapからfind関数を用いて検索する際に、
std::string_viewを利用して検索をかけたいのですが可能でしょうか?
もしくはstd::string_viewを利用して検索する方法等はあるのでしょうか? 色々ご意見ありがとうございます。
>>279,280,281
後出し情報で申し訳ありませんが、バイナリファイルを読み込んで
そのバイナリデータの途中に別のレコードを追加したり、
削除したり、文字列置換したり、
といったことを行い、最後にファイルに書き出そうと考えています。
>>286
ご推察の通り、データを読み込んで一部を加工したファイルを出力しようとしていました。
>>282,285
サンプルコードありがとうございます。
ふんだんにc++の文法が使われているので、作っていただいたサンプルコードを今調べているところです。。
まだc言語レベルの記述しか理解できていないので。
とりあえずイテレータ部分を調べています。
加工しやすいように一度内部で数値や文字列に変換したdatabaseを作り、それに対し追加、削除、文字列置換などの加工をしてファイルに出力する。
というフローを考えていましたが、みなさんのご意見を参考にファイル出力するときに加工しながら出力する方式で検討してみようと思います。 >>287
型をmap<K,M>の代わりに
map<K,M,std::less<>>にしておく >>288
> そのバイナリデータの途中に別のレコードを追加したり、
> 削除したり
と言うことならvectorよりlistの方がいいと思う >>290
ご意見ありがとうございます。
listがいいと思うのは任意の位置に挿入したりできるから。
ということでしょうか? C++ は C と互換性があって C の延長線上でも使えるのが利点だとは C++ の設計者自身も言ってるけど、
C の延長線上で使ってたらやっぱり C の延長線上な設計になっちゃうと思うんだよなー。
その延長線を伸ばしていっていずれ C++ の習得に至る (あるいは至らなくてもよい) 、みたいな想定らしいんだけど、
今となっては C から C++ の距離がデカすぎる気がしてる。
だからどうするのが良いという意見はないのでぼんやりした感想でしかないけど。 今や互換性があるというよりも使いやすいFFIがあるって認識のがメジャーだろう。 >>277
codepadはC++03だったと思うが、03では構造体のメンバの=によるデフォルト初期化は
(static constな、配列でない組み込み型を除いて?)許可されてない
ので14が使えるideoneになるけどとりあえず最低限動くようにした
https://ideone.com/1RUIfn
どうしても03じゃないと困るなら直す
あとRuntime Errorって出るのは単にmainで1を返してるから(0にしたら直る)
特に関数の戻り値を使いもしないのに常にintにしてreturn (1)って書くのやめたほうがいいよ
>>292
>今となっては C から C++ の距離がデカすぎる
そう思うなら余計な改変はしないでやれよ あ、そういえばバイト列全部持ってるから別にサイズ入れる必要無かった >>291
そう、
> itemの数が膨大にあり
の状況でvectorに挿入/削除したら死ぬ
> 速度がほしい
のに対してlistが最適かはわからんけどvectorより100倍マシ >>296
vectorについて調べてみました。
>ttp://vivi.dyndns.org/tech/cpp/vector.html
上記に下記がありました。
>insert() の処理時間は O(N) 。O(N) とは配列要素数に比例して処理時間を要するという意味。 データ数が100倍になると、処理時間も100倍になる。
>それに対して push_back() は O(1) なので、データ数がいくら増えても常に一定時間で処理が終わる。
大量のリストで先頭の方に挿入するとやばそうですね。
これは気にしていませんでした。
ありがとうございます。 listは要素を手繰るのがクッソ遅いから、事前に挿入位置のノードのポインタを知っている状況でないといけないことに注意
毎回前からスキャンして挿入なんてやってたら結局O(N)でメモリアクセス効率がゲロ悪い分だけvectorより遥かに遅い C89とC2xの距離も大きくなってるけどな
あっちがこっちに寄ってきてるから >>298はなぜかvectorだと瞬時に検索できると思ってるw ていうかとりあえず組み上げてから実測した方がいいよ、似たようなことはすでに言われてるけど >>297
vector の方が先頭に追加するのが速いこともあるという観測データが有る。
https://cpplover.blogspot.com/2017/02/c-p0550r0-p0601r0.html
今時の機械は事情が複雑すぎて予想できない。
まず実測しろってよく言われているのはこういうこと。
やってみてからどこが効いてるのか調べた方がいい。 >>300
少なくともlistに比べたら瞬時だね
さすがに挿入位置まで毎回スキャンしてたらlistに勝ち目はほぼ無いから、そこで突っかかるのはさすがに無理筋
listを擁護したいなら先頭への挿入か挿入位置のノードのポインタが既知のケースに話を限定しなさい >>305
> 少なくともlistに比べたら瞬時だね
えっ、何その魔法w 挿入が主な目的な場合って普通はheap使うんじゃねーの?
あんまり任意の位置に挿入するってシチュエーションはないように思う。 >>304
そういうこともあるんですね。
プログラムは難しい。 >>307
heapからのメモリを繋ぎ合わせた集合体がリンクリストで、それがSTLでは
std::listになっている。 >>298
Cでは、リンクリストを使って、ノードの位置を保持するためには、index値ではなく、ポインタ値を用いる。
STLでは、index値を前面に使う設計になっているのが問題。
元々、リンクリストは、ノードを巡るのは非常に高速。
ノードの位置をポインタで維持している限り「検索」作業は入らない。 std::listには問題が有るかもしれないが、リンクリストというデータ構造自体は、文字列(string, CStringなど)のクラスを作るためなどをの一部の例外を除いては、動的配列よりもほぼ全面的に優れていると言っても過言ではない。 本来は、Cの最も優れている点を言えといえば、そのリンクリスト一点と言っても過言ではない。 >>310
stlでは、ノードの位置を維持するために、先頭を0として、0,1,2,... というような「連番」で管理しようとしてしまう。
そのために、リンクリストである所の std::listを使う場合、先頭から順番に「たどる」作業が必要になってしまい、>>298が言うような「クッソ遅い」現象が起きる。
しかし、それは、stlの設計のクソさによるものである。 >>313
> 「連番」で管理しようとしてしまう。
なんで?
std::list のイテレータは実質的にポインタだしそれで記憶しておくもんじゃないの? この前からヒープヒープ言う小僧がいるけど
普通ヒープといえば
- 木構造のヒープ
- ヒープメモリのヒープ
どっちだと思う?
おれは後者だけど 文脈によらない「普通」なんてないだろ。
「ヒープ」と出てきたらどっちの意味で使っているのか注意しなきゃならない。 >>314
そうなのか。
だとしたら >>298 が言っていたのはなんなんだ? 下記のようにすると、最後にprintfしているときにはnameに値が入っていません。
set()を抜けたときに開放されてしまうのではと思うのですが、どうすれば保持出来ますか?
char* name; のところを char name; にはしたくないと思っています。
mallocとかを使うのでしょうか?
class AAA{
public:
char* name;
};
int AAA::set(){
char temp_name[5]; ←ここで確保した変数がset()が終わると開放されてしまう??
temp_name = "NAMAE";
name = temp_name;
return(1);
}
void main(){
AAA aaa;
aaa.set();
printf("NAME %s\n", aaa.name);
} >>298
例えばテキスト・エディタを作っている場合、ある一点Aに50文字を挿入する
というようなことがおきる。
この場合、50文字を挿入する前に、Aの場所のノードのポインタ値を求める。
カーソルの位置に挿入する場合には、最初からポインタ値を持っているようにしていれば「求める」必要は無い。
一度ポインタ値が分かった後は、50文字追加する際に挿入場所として必要なポインタ値は長々と最初から「たどる」ことなく分かる。
たどる場合も、各行の先頭のポインタ値をすべて保持するようにしておけば、まず行Yの先頭のポインタ値を見つけて、あとは、そこから列Xのポイント値を求めるための計算量は余り多くは無い。
このような場合、全てのデータをstd::vectorのような動的配列で保持しようとするのは基本的に速度が遅くなることが多いが、リンクリストは速度的に安定する。 >>317
vector と同じように考えるなってことを言ってるだけだと思うよ。
逆に vector では要素の追加とかがあった時にイテレータが無効になるので、
あまりイテレータで保持すべきではないという事情がある。
コンテナとして最低限度共通のインターフェイスが付いてるけど、
やっぱり内部の事情は意識しなけりゃなんねぇなぁという話。 スコープ抜けたら当然解放されるよ
c++ならchar*じゃなくてstd::stringでも使った方がいいのでは >>320
例えばの話、要素数が多いような巨大なデータを動的配列で確保したとする。
この動的配列のトータルバイト数をW(バイト)としよう。
この配列の要素数が、本当の意味で増やす動作が入ったときには、メモリの容量が
一時的に 3*W(バイト)必要になる。
Wが実メモリのぎりぎりに入るくらい大きい場合には、仮想記憶が必要となりとても遅くなる。
一方、リンクリストだとそのようなことがない。 >>321
後半部。
そういえば、vectorの場合、途中にデータを追加した場合、それより後ろのindex番号がずれてしまうので、その部分を指していた今までのイテレータは使えなくなってしまうのだね。 >>318
構造的には存在しない。
リンクリストを使う場合、ノードを指し示すためには出来る限りindex値ではなくポインタ値を使うようにして
「順繰りにたどる」
必要が無いようにする必要がある。 >>324
それもあるけど vector は要素が連続しているという強い制約があるから場所が足りなくなったら再配置することがある。
realloc みたいなもん。 いやポインタ使おうが無理でしょ...
リンクリストだとポインタ飛び飛びになるんだから辿らないと無理でしょ >>327
もちろんどこかでは辿るが、辿った結果をインデックスとして保持してたらコストがデカいから
ポインタ (イテレータ) で保持することを心掛けてねっていう意味だと思うよ。 それだと298のいってること理解できるはずなんだけどね
ようわからんわ >>327
「たどる」と言っても、隣のノードをたどる場合、コンパイル後のマシン語レベルだと、整数に1を足すのと同じか、その2回分程度のクロック数しか消費しない。
だから for 文で巡るときには、動的配列を巡るのと全く同じ程度しか時間が掛からない。 >>329
恐らく、>>298 は、リンクリストの効率の良い使い方を知らないと思われる。 この教科書読めレベルの話、いちいち議論する必要なくね? >>331
どうみても理解してると思うが
どこがおかしいとおもってるの >>333
「事前に挿入位置のノードのポインタを知っている状況でないといけないことに注意」
この命題自体は正しい。
しかし、「ポインタを知っている状況ではない」という状況自体が、C言語流の
文化では滅多に起き得ないことだからだ。
恐らく >>298 を書いた人は、「ポインタを知っていない状況」が高頻度で起きる
ような書き方をしているからこそそのような注意を促したと感じる。
多分、C言語とは異なる文化に長く親しんだか、少なくともC流の文化に慣れずにいきなりC++から始めたかのどちらかだと思われる。 >>335
または、ポインタが理解できないか、ポインタにアレルギーがあって、避けて通ってきた人かも知れない。
そういう人は多いらしい。
聞いた話だとポインタを全く使わずに配列だけでC言語を使っている人がいるそうだ。 要はlistとvectorの違いは何で、なぜ必要かという文脈でいいのかな
listはfor文にi++入れないための単なる糖衣構文だと思うが
基本的に自分は糖衣構文は必要ない派です リンクリスト万能君も老害リストに追加だね
キャッシュヒット率低いし、64bitポインタの無駄もでかいし
メモリ空間異なるところもっていくときに全部作り直しだし
昨今はむしろ使えないデータ構造扱いされること多いから
c/c++を高速化のために使ってるならなおさら >>338
測定すればすぐわかる事なのにね。
そもそも教科書は挿入に焦点を当ててるけど、検索のほうがよほど問題。
algorithmと極端に相性が悪い。
listを使う理由はイテレータの安定性のみ。 >>340
測定だけでは見落とすことが有る。
測定しただけで std::vector の方が速いと思っている人は、数学的想像力が足りてない。 >>341
だってキミ嘘しか書いてないやん。
最初から全部嘘だし。
どう見たって釣り師。 >>342
恐らくIQが高いので一般プログラマはついてこれない。 はいこのおじいちゃんの毎度の捨て台詞いただきました > algorithmと極端に相性が悪い。
> listを使う理由はイテレータの安定性のみ。
とか書くような奴もどうかと思うわ 話者に対してレベルが低過ぎる人には話が嘘か間違いにしか聞こえない。 嘘つきがレベル高いってのは
赤軍派の暴力事件が相次いでいた頃の
共産主義=インテリのステータスだった時代の
今となってはもうみんな気付いている茶番とインテリぶったやつらが
真っ赤な最高学府で安々と洗脳されたバカばっかりだったという
お笑いぐさのやつだね 動的配列より全面的に優れているって何かのギャグなの?w >>336
Cに慣れた人間がリンクリストを好む傾向があるのは、
動的配列が一段抽象化層を設けないと扱いづらいのに対してリンクリストはCの自然な構文で生のままで扱いやすいからだよ
君自身も君が馬鹿にしている「癖」に縛られているんだ >>349
仮に IQ が存在するとして、 IQ に差があるのならば、IQの低い受け手はIQの高い話し手の発する全情報を解釈するのに困難を感じることは確かにあり得るとは思いますが、
「嘘か間違いにしか聞こえない」というのは、IQの差だけでは説明できないと思います
IQの低い私の体験としては「わからない」とはいつでもよく感じていたりするのですが、それでも「嘘だ」「間違っている」とは普通は考えませんね リンクリストって今時のCPUにとって非常に性能上扱いづらいものだからねぇ
順繰りにたどっていく場合に先読みがしづらい
実体を指すポインタの配列なら2つ先、3つ先のアドレスまでキャッシュに載っているから、プリフェッチが効いて必要になる頃にはキャッシュにロードされてる感じになる >>345
ここにはお前と話が通じない一般人しかいないから、お前と話ができる人がいるどこかよそに行った方がお互い生産的だと思うぞw >>356
デタラメではないでしょ
キャッシュヒット率意識するのは大事 プリフェッチとか色々ごっちゃになってる
断片的な知識で知ったかしようとして失敗してるパターン 要素アドレスが連続した領域に書き込まれている場合は、
コンパイラがループアンローリングして次の要素アドレスロードしてその参照先のプリフェッチ命令挿入することが可能
ってのを場合によっていくつか先まで出来る
リンクリストの場合はこうはいかない
次の要素のロードが終わらないと次の次の要素のアドレスが分からんのだから インテルCPUの場合はプリフェッチ入れなくても投機的にプリフェッチされてたからこそ、例の脆弱性が問題になってた 実装法を理解できてないために効率よい使い方を間違っている人は遅さをすぐにキャッシュせいにしてしまう。 >>355
まあそうだが、それだとおまえら一般人はいつまでたってもアホなプログラミングしかできないだろうな。 >>362
俺の人生経験からすると、現実には本当に馬鹿な人にはいくら言っても無駄なようだが。
いくら言っても理解できないし、強く何度も言うと、逆に明らかに絶対やっては駄目なときでもいつもそればっかりやってしまうようになったりする。
なので周りはむしろ困ることになる。 cppreferenceを含めてネットでは std::vector ばかり使われているのは、大部分のプログラマがポインタを理解できないのでリンクリストも理解出来ておらず、使いこなすことが出来ないためと踏んでいる。
正しく理解できないためにstd::listを使うと悪い使い方しかできないため、彼らの実験の仕方ではいつもstd::vectorより遅くなってしまう。
そのような人には、C++を使ってもC#以上の速度を出すことは困難で、だからこそ一般プログラマとそれ以下の人材しか集めることの出来ない多くのプロジェクトでは C#やJava,Rubyなど簡易言語が好まれて使われるようになっていると予想される。
俺とは住む世界が違うので、このことは推定に過ぎないがな。 uint64_t の型から unsigned char の型に変換するにはどうすればよいですか?
同じ4バイトなのでどうにかすれば変換できるのではと思っているのですが。 間違えました。
unsigned charは4バイト確保すれば同じバイト数になる。ですね。 そのマシンのエンディアンの通りに格納したんでいいなら
uint64_t a;
unsigned char b[4];
reinterpret_cast<uint64_t &>(b) = a; std::vectorばかり使われる最大の理由は、C言語における配列と互換性を持つ唯一のコンテナだからでしょ。 >>367,369
間違えました。
8バイトだからこうなるんですね。
変換後の中身を確認したらエンディアンも問題なさそうです。
ありがとうございました。
uint64_t a;
unsigned char b[8];
reinterpret_cast<uint64_t &>(b) = a; >>372
動くだろうけどよくないやりかた
reinterpretじゃなくてmemcpyを使う
それかアライメントを合わせる >>373
ttps://stackoverflow.com/questions/49648033/c-convert-uint64-t-to-unsigned-char-array
上記を参考に下記でやってみたらこれもうまく行っているようです。
こんな感じでしょうか?
uint64_t a;
unsigned char b[8];
memcpy(b, &a, 8); >>364
あなたが書いてることのレベルが低過ぎて理解できません。 ああそうか、アラインメントのこと完全に忘れてたすまん
まぁmemcpy, またはunsigned charにアラインメント指定か、もしくはunsigned charごとに代入した方がいいね
動かす環境が限定されてるならreinterpretでもいいけど それでいいよ
ちなみにmemcpyの呼び出しコストは最適化で消えるから気にしなくていいよ
(コンパイラ依存だけど) 追加で質問があります。
http://codepad.org/uN82gnco
この30〜31行目でemplace_back()、back()を使っているのですが
emplace_backを使うときはこうやって使うのであってるのでしょうか?
あと、上記をコンパイルすると下記エラーが出ます。
「エラー: オブジェクト以外がメンバ関数 ‘int Self::xxx(ITEM)’ を呼び出すことは出来ません」
今色々調べているのですが、何が悪くてどのように解決すれば良いかがまだわかりません。
どうすればよいかわかりますでしょうか? >cppreferenceを含めてネットでは std::vector ばかり使われているのは、大部分のプログラマがポインタを理解できないのでリンクリストも理解出来ておらず、使いこなすことが出来ないためと踏んでいる。
よくこんな頭の悪いこと思いつくよなw How can you be so certain? Self::xxxをSelfの後に書かないと。
ラムダ内部は別の関数だからthisにはアクセスできない。[&]を使うとか工夫しないと。 >>379
emplaceを試したいならまずは余計なものいれずにやるべきだね
struct ITEM {
ITEM(const char* p) : name(p) {}
std::string name;
};
std::vector<ITEM> items;
items.emplace_back("ABCD");
for (auto& item : items) {
printf("FF %s\n", item.name.c_str());
} >>382
"&"を使うということは構造体をポインタ渡しするということでしょうか?
下記でポインタ渡しにしたつもりですが、同じようなメッセージが出ました。
ポインタ渡しのことではないのでしょうか?
http://codepad.org/L0oOc9RF
ほぼ同じエラー →「エラー: オブジェクト以外がメンバ関数 ‘int Self::xxx(ITEM*)’ を呼び出すことは出来ません」
>>383
サンプルありがとうございます。
emplace_back()の時に直接引数に入れることができるんですね。
参考にさせていただきます。
クラス関数に構造体を渡すとエラーになったので、その質問をしたついでにemplace_back()の使い方の質問もさせていただきました。 >>384
> emplace_back()の時に直接引数に入れることができるんですね。
それをやりたいからこそのemplaceだよ
無駄を省きたい上級者用って感じだね
まずは自分でITEMを作ってpush_backで追加するのが基本だと思うよ 違う違う、[](ITEM& item) を[&](ITEM& item)にしろってこと >>385
emplace_backは新しい文法でpush_backの方が従来のもののようですね。
>>386
その対応でエラーが消えました。
[&]が何してるのかまだ理解できていないので調べてみようと思います。
ありがとうございました。 あっと、[&](ITEM& item)より[this](ITEM& item)のほうがよかったか >>388
thisでもいけました。
数値のmemcpyを教えていただいた >>374 の件ですが、下記で確認するとバイト単位で逆になりました。
エンディアンの影響だと思いますが、unsigned charに反転せずに簡単にセットする方法はなにかありますでしょうか?
unsigned short num = 258;
unsigned char temp[2];
memcpy(temp, &num, 2);
printf("A %04X\n", num);
printf("B %02X%02X\n", temp[0], temp[1]);
下記結果になる。
A 0102
B 0201 >>389
調子にのりすぎ
原因わかってんなら自分で解決できるだろ
頭使え >>390
すみません。
センスないような気がしますが下記で入れ替えようと思います。
unsigned char temp1[2];
unsigned char temp2[2];
memcpy(temp1, &num, 2);
temp2[0] = temp1[1];
temp2[1] = temp1[0]; >>391
htons を使えばいいんじゃね?
言語仕様にあるわけじゃないけど、 POSIX と Windows で使えるからまあおおよそポータブルでしょ。 >>391
素直に
temp[0] = (num >> 8) & 0xff;
temp[1] = (num >> 0) & 0xff;
でよくね? >>372
コピーも何も必要なくて、
uint64_t a;
BYTE *ptr = (BYTE *)&a;
ptr[0] : 0 バイト目
ptr[1] : 1 バイト目
・・・
ptr[7] : 7 バイト目
でいける。 >>395
さらに、
union UUU {
uint64_t m_u64;
BYTE m_b[8];
};
uint64_t a; // 入力値
UUU u;
u.m_u64 = a;
とすれば、
u.m_b[0] // 0 バイト目
・・・
u.m_b[7] // 7 バイト目
となる。 >>396
それc++ではUBだよ
あれ君って天才君だっけ? 汎用的に作るならこんな感じかな?
#include <type_traits>
template<class T>
typename std::enable_if<std::is_integral<T>::value && std::is_unsigned<T>::value, void>::type
integral_to_bytes(T n, std::uint8_t* dest) {
for(std::size_t i=sizeof(n)-1; i<sizeof(n); i--, n/=256) dest[i] = n%256;
} std::array<uint8_t, sizeof(T)>を返す方が親切だぞ >>399
なるほど。
整数型の大きさだからそれほど大きくなることは心配しなくていいもんな。 OMP_STACKSIZEが小さいとセグフォるが1Gとか指定してもいいんか? >>403
typedef union
{
uint32_t u32RawData;
uint8_t au8DataBuff[4];
} RawData;
uint32_t ChangeEndianness(uint32_t u32Value)
{
RawData uChangeData,uOrginalData;
uOrginalData.u32RawData = u32Value;
//change the value
uChangeData.au8DataBuff[0] = uOrginalData.au8DataBuff[3];
uChangeData.au8DataBuff[1] = uOrginalData.au8DataBuff[2];
uChangeData.au8DataBuff[2] = uOrginalData.au8DataBuff[1];
uChangeData.au8DataBuff[3] = uOrginalData.au8DataBuff[0];
return (uChangeData.u32RawData);
} C/C++では高速化のためCPUのマシン・アーキテクチャをそのまま使う。
マシン・アーキテクチャによって little endian と big endian の違いが有るのでC++言語仕様としては定義されてないが、「but most compilers define」なっている。
これはつまり、littele endian の CPUなら、そのまま little endian での表現がそのまま読みとられ、big endian の CPUなら、そのまま big endian での表現がそのまま読み取られることを意味している。
たとえば、cppreference では、
「reading from n or c is UB but most compilers define it」
となっており、
32BIT値の 0x12345678の場合に、unionで 16BIT 配列の0要素目に0x0011を代入すると、
0x12340011 or 0x00115678
が読み取られるように書いてある。
undefined behaviour であっても、このどちらかに限定されると言うことであろう。
https://en.cppreference.com/w/cpp/language/union
union S
{
std::int32_t n; // occupies 4 bytes
std::uint16_t s[2]; // occupies 4 bytes
std::uint8_t c; // occupies 1 byte
}; // the whole union occupies 4 bytes
int main()
{
S s = {0x12345678}; // initializes the first member, s.n is now the active member
// at this point, reading from s.s or s.c is undefined behavior
std::cout << std::hex << "s.n = " << s.n << '\n';
s.s[0] = 0x0011; // s.s is now the active member
// at this point, reading from n or c is UB but most compilers define it
std::cout << "s.c is now " << +s.c << '\n' // 11 or 00, depending on platform
<< "s.n is now " << s.n << '\n'; // 12340011 or 00115678
} 先月ぼくが通った道だけど、結論が全く違ってて興味深い。 >>403
cではOKなんだよ
だからわざわざc++ではって限定したんだから察せよ
cでは定義されてるから多くのコンパイラーはc++でも同様の解釈する
また実際のところ今後ずっとそうだろう(今回のケースに限っては)
でもUBはUB
屁理屈つけて自己正当化しようともそれは変わらない
エンディアンでなくライフタイムの問題でしょ、c++の常識的に >>405
ほとんどの場合に大丈夫だろうという見立ては間違ってないと私も思う。
で、大丈夫でなかったときは?
たぶんコンパイルエラーにも警告にもなることなく黙って未定義動作に突入する。
各処理系・環境での挙動が保証されている (検証が済んでいる) なら別に使ってもいいんじゃないのとは思うけど、
union を使ってすごく良くなるというわけでもないので、あえてやることもないんじゃないのとも思う。
少なくとも最初は選択肢から外すなぁ。 本人わかってんだからそんな必死になって噛み付くようなことでもないだろ
だいたいプラットフォーム全く限定せずにC++でソフトが書けるのかと
>>411
>たぶんコンパイルエラーにも警告にもなることなく黙って未定義動作に突入する。
アホか
普段警告レベル下げてるから気付かねーんだよ (↑のv はミスしました)
>>409 >>411
実は、union より、>>395 のように単純に書いたほうが良い。
unionの場合は、最初に代入によるコピー動作が入るが、>>395 は、単に 64bit 整数の入っている変数のアドレスを取得しているだけだから、全くコピー動作が入らず、物凄く効率が良いし、未定義動作でもない。
>>395 が未定義動作というなら、Cの根幹が揺るぐ。 >>409
little endian と big endian の違いだけで全面的にUBということではないはず。
unionの仕様からいえば、ちゃんと 64BIT 整数をそのままイメージとして投影したものがバイト配列になって取得できるはず。
それがunionの定義なのだから。
sizeof(union型)とsizeof(unionのメンバ)の関係も定義されているので、それ以外の実装は有り得ないはず。 >>415
お前は人のレスよく読め
cの話はしてないんだよ private/protectedで隠されているわけでもないPODの
ビット表現に依存するなってのは理に適わない
規格が保証しないなら自己責任というだけの話
そんなんどこにでもいくらでもある >>416
>>396 で言えば、m_u64, m_b メンバの先頭アドレスがどちらも offset 0 から始まっている限り、little endian と big endian の違いを除いては、どんな処理系でも、m_64 のメモリ中での表現がそのままバイト配列 m_b[] に投影されて読み出せる。
それがunionの定義。
メンバがすべて「offset 0」に配置されるかは、アラインだけの問題。 >>415
規格では全面的に UB だよ。
C++11 の 9.5 を確認してみたんだけど、
共用体で保証されているのは
- 直近で入れたのと同じメンバで取りだす場合
- 先頭部分に共通する型を持つ標準レイアウトの型をメンバとして持つ共用体であれば共通部分を使うのはアリ (← 言い回しがややこしくてスマン)
ってことだけで、あくまでも先頭に適合する型が連続する部分に限って許してる。
そんでもってこれは規格の書き方はちょっと違うだけで C でも同じだわ。 >>419
自称天才さんですらUBであることは認めてんのにお前ときたらw
まぁ後は好きにどうぞ コンピュータはチューリングマシンではない!!!
理由 ---- timeGetTime();
マザボの時計は計算不可能的だ、時計を計算できる「アルゴリズム」は存在しない
理由2 multi-thread チューリングマシンはシングルスレッド的だ
理由3 multi-process シングルスレッドで並列計算を真似る
―― つまり、チューリングマシンなる理論自体はそもそも間違っている!
なぜなら単一のチューリングマシンは並列計算を真似ることができる
つまり、チューリングマシン自体は矛盾している!
(たとえば p->Update(); q->Update(); これはシングルスレッドのコードだ、
つまり、単一のチューリングマシンだ、しかし実行時の効果は並列的だ!) char配列とunionにしてバイトアクセスなんて
みんな自己責任でやってるに決まってるだろうが
そこへ、その案件の関係者でない者が頼まれもしないのにしゃしゃり出て
「UBだ」とキリるのが格好いいと思っているのはそいつ自身だけだ >>423
分かってる奴が自己責任でやってるだけなら誰も止めないよ。
今回の場合、初心者の質問(>>389)に対し自称上級者がunionを使う方法(>>396)を提示したから、それはUBだと突っ込まれたんだろ。
別にUBを指摘することがカッコ良い訳ではないけど、指摘されて真っ赤になることはカッコ悪いぞw ああ、=にしたいわけね
いいよ別に
こっちも証明できねえし
ただ、おまえさんのアドバイスは俺の胸には全く響いていない
その事実が変わらん限り痛くも痒くもない >>420
しかし、メンバのアラインの問題さえクリアしていれば、union中の2つのメンバの
offset address は 共に0になる。
そして、以下の通りなので、メモリ中の同じアドレスから読み書きすることになるので、C++の仕様に明示されていなくても、m_b[k] の動作は単純に、m_u64のメモリ中のイメージをそのまま先頭から読み書きすることになる。
なので、問題が起きるとすれば m_u64 と m_b のアラインの問題のみだ。
もし、アラインが合わなかった場合には、m_b[k] が k == 0 でも、m_u64 の途中のアドレスから読み出すことになったりする事になる。
しかし、この様な場合に m_u64 と m_b のアラインが合わない処理系は多分、珍しい。
union UUU {
uint64_t m_u64;
BYTE m_b[8];
};
UUU xx;
xx.m_u64 // もうこの段階で、コンパイラ内部では m_u64 が元々 union のメンバであったという情報は消えることになることが C/C++ の仕様では保障されている。。
xx.m_b[k] // もうこの段階で、コンパイラ内部では m_b が元々 union のメンバであったという情報は消えることになることが C/C++ の仕様では保障されている。。 >>423
自己責任とかじゃねーっての
cでは合法的なtype punning
お前strict aliasing理解してるか? やっぱりUBの怖さ全然わかってない子か
おっしゃる通りオフセットのアドレスはたまたま一緒かもしれないし、規格を読み解けば論理的にそうなるべきであることは導けるのかもしれない
だけどそれが何だというのか?
そのオフセット値から読み取ってくれることや、そもそも読み取り動作をしてくれるとどうして言い切れる?
未定義動作ではコンパイラが何をするのも何をしないのも完全に自由だということをお忘れなく https://stackoverflow.com/questions/25664848/unions-and-type-punning
4. THE SAFE CASE: unsigned char
The only safe manner of using type punning is with unsigned char or well unsigned char arrays (because we know that members of array objects are strictly contiguous and there is not any padding bytes when their size is computed with sizeof()).
union {
TYPE data;
unsigned char type_punning[sizeof(TYPE)];
} xx;
Since we know that unsigned char is represented in strict binary form, without padding bits, the type punning can be used here to take a look to the binary represention of the member data.
This tool can be used to analyze how values of a given type are represented, in a particular implementation.
I am not able to see another safe and useful application of type punning under the standard specifications. >>427
いーや自己責任だ
おまえさんが知らないだけ
どの案件の関係者でもなさそうだな >>429
その回答の下に「Cだけだろ」ってツッコミ入ってるだろ
このあわてんぼうさんめ >>430
何を根拠もなく断言しとんねんこの老害
cppreferenceはっとく
これ基本的に規格に書かれてる文と同じだ
かつこれはcにしか書かれてない
c++のは下にリンクあるから読んどけ
ttps://ja.cppreference.com/w/c/language/union
共用体の内容をアクセスするために使用されるメンバが、値を格納するために最後に使用されたメンバと同じでない場合は、格納された値のオブジェクト表現が新しい型のオブジェクト表現として再解釈されます (型のパンニングと言います)。 >>426
メモリのレイアウトの話だけならそれ以外の選択肢は実質的にないだろってのはわかるよ。
そりゃそうだ。
実質的にそうだってのは今さら言わなくても知ってる。
いまどきの C++ コンパイラは未定義の挙動はどうなってもいいことを前提にした最適化をすることがあるんだよ……。
去年には LLVM が const 変数への代入を削除するってのでニュースになっただろ。
https://developers.srad.jp/story/19/09/27/1626210/
const 変数は変更されない。 それが前提なんだから変更されても知らんってわけ。
今まで緩く対応してたのが厳しくなることだってある。
共用体が使われる場面ってのはメモリのレイアウトを利用したい場合ってのは多いから
現実には急に挙動を変えるなんてことはないと思うけど、
未定義を警戒するのは最適化に対する警戒なんだよ。 このスレみててなんとなく餃子くいたくなったからスーパーいったけど
売りきれてたわ >>432
次も非常に重要:
「共用体へのポインタは、そのいずれのメンバへのポインタにもキャストできます (共用体がビットフィールドを持つ場合は、共用体へのポインタはそのビットフィールドのベースとなる型へのポインタにキャストできます)。
同様に、共用体のいずれのメンバへのポインタも、囲っている共用体へのポインタにキャストできます。」
これは、union においては、全てのメンバの先頭アドレスが、すべてoffset 0から始まることが保障されていることを意味する。
なので、>>426のアラインの心配はない事になる。 >>435
もとい。良く考えてみるとそうでもなかった。
unionへ、または、unionから cast する際にコンパイラが何らかの offset 値を足したり引いたりする可能性があるため。 >>432
もう一度言う
どの案件の関係者でもなさそうだな >>437
おっ。 立場を持ち出すのか?
理屈では反論する余地がないという意味? お? =ってことでいいのか?
ID変えるとか超しょーもねーねらーだなw >>433
「const 変数を cast してから代入する」というのはそもそも元々禁止事項だから、今回の話とはかなり違う。 >>441
禁止と未定義の間に差があるという誤解? >>407, >>438
こいつらすごい嬉しそう
こういうのでしか偉そうに出来ないんだろうなぁ >>445
>>442 には、以下の用になっている:
// at this point, reading from n or c is UB but most compilers define it
std::cout << "s.c is now " << +s.c << '\n' // 11 or 00, depending on platform
<< "s.n is now " << s.n << '\n'; // 12340011 or 00115678
「 11 or 00, depending on platform」
「12340011 or 00115678」
数学的に
A or B
ということは、A または Bに限られると言うことで、それ以外の可能性がないことである。 いや、さすがにそれは「大抵のコンパイラはどちらかに定義する」だから
そうじゃないのも有り得る
ただそんな変な環境まで想定するのも非現実的だし
それを言うなら1byte=8bitsとも限らないんで、そんな環境だとuint8_tもおそらく定義されておらず
はちみつがドヤ顔で自称汎用的だと挙げた>>398も使えないわけだが >>444
それだったら UB という語を使うのがおかしいよ。
C++ (の仕様) 的には UB ってのは正しいプログラムには存在してはいけないものだ。
どちらになるのか不定という意味では普通は使わない。
11 or 00 は most compilers define it に対応してるとも解釈するのが自然だと思うよ。
>>445
せやな。
そこを言うと汎用的とは言えないな。
unsigned char で定義した方が確実だったか……。 C++20 では負数は2の補数形式で定義されることになったみたい。
C++ の最新規格に追従しているコンパイラは全部 2 の補数を前提にしてたからもう 1 の補数はええやろみたいな話を聞いた。
そこまで決めるのになんで1バイトの大きさは明記しないんだろ。
1 バイトが 8 ビットじゃないアーキテクチャ (で主要 C++ コンパイラがサポートしている環境) が有るんかね? >>445
十分に汎用的とは言えないけど使えないときはコンパイルエラーになるだろうから比較的マシということで勘弁。 >>447
signedのwrap aroundは定義された? >>449
ID 変えとかはしてないからね。
いまどき匿名プロキシとかあんまりないし。
俺がトリップを付けないのはつまらない質問するときだけ!
(つまらないこと聞くの恥ずかしいじゃん……///) >>451
人のことを=っといて虫のいいことを言うな
人間としてどうなのか疑っちまうぜ >>450
されてない。 それは従来通り。
何故なのか……。 【ソフト名】リソーエディタ
【URL】https://github.com/katahiromz/RisohEditor
【説明】リソースデータを編集できるソフト。
これ、VS2012でビルドしたら、バイナリサイズが10MB超えてるだけど、なんとか6MB以内に縮小できないだろうか?
インラインとか関係ある? >>455
デバッグ情報は取り除いてそのサイズ?
サイズだけが重要なら UPX とか使えばいいんでね。 >>456
うん。zip圧縮したサイズがだいたい10MB。UPXも試したけど圧縮後のサイズには効果が薄いみたい。インライン関数がデカいのがまずいのかな? >>457
サイズ優先の最適化オプション試してみたら そもそも >>398 って、割り算と剰余まで使っていて、実用的なコードとは
言いがたい。
せめて、x >>=8 と x & 255 ならまだましだが、そもそも >>395
で十分なのに、敢えて複雑にして、逆にバグが入る可能性も高い。
それと、厳密に言えば、誰かも指摘したように unsigned char が 8bit かどうか
も C や C++ の仕様としては決まってないようだし。 >>398
それはバイトの概念を直接扱えないような言語でも使えると言えば使えるかもしれないが、敢えてそんなコードを書く必要はない。
「高級アセンブラ」の名が無く。
自分が知らない処理系に誰かがコンパイルすることを想定していて不安が残る場合には、どこかに
テストコードを書いておけばいい。例えば、次のようにする:
uint32_t a = 0x11223344;
uint8_t *ptr = (uint8_t *)&a;
if ( ptr[0] == 0x44 && ptr[1] == 0x33 && ptr[2] == 0x22 && ptr[3] == 0x11 ) {
// リトルエンディアン
}
else if ( ptr[0] == 0x11 && ptr[1] == 0x22 && ptr[2] == 0x33 && ptr[3] == 0x44 ) {
// ビッグエンディアン
}
else {
// エラー
} CではOK、C++ではUB
C/C++コンパイラではたまたま動く場合が多いかもしれないけど、UBはUBなんだし回避方法もあるんだからやめとこう
ただこれだけの話なんだけど
何が気に食わないのか「わかりやすいんだ!汎用的なんだ!Cらしいんだ!俺のコンパイラでは動くんだ!この程度のテクニックも知らんのか!」
ってノリでナイーブにUB書きたがる奴が絶えないのはなんでだろうね
一度でもそういうのが引き起こす地獄みたいなバグに付き合わされたら二度とそんなことしないしさせないって思うもんなんだけどね
幸運にも遭遇したことがないのか、全部他人に解決してもらってるいい身分の人なのか 「そんなにお酒飲み過ぎると健康に悪いよ、やめとこう?」
「一生酒を飲むなと命令するのか!何の権利で指図するんだ!」
おおめんどくさい
ただのアドバイスを命令や強要や脅迫に感じるのは鬱の初期症状だから気を付けなよ お節介じゃないよ
俺の関係者がここを見てここのバカに勇気付けられてUB書き散らかすようになると俺が困るから言ってるんだよ
俺のためだ 逆もしかりだ
チームに入ったばかりの新入りが「UBだ! UBだ!」と喚きだし
「おまえならどうする?」に答えられないゴミには諦めてもらうしかない
どうせunion使わないためにポインタのキャストとかだろくっだらねえ 新入りに危険な書き方を指摘されたら「くっだらねえ」と逆ギレした上に
チームで規格を当たって検討もせずに新入りに解決策を丸投げするのか
最低だなお前 >>459-460
まともなコンパイラはビット演算に置き換える最適化が入ることが期待できるんだから、
割り算が実用的でないなんてことはないよ。
エンディアンの影響を避けるには良い選択のひとつだ。 ガチで組み込み環境のシビアなやつだとバイナリのテストの方に時間をかけたりするから
逆に言語に無頓着になる場合があるというのは聞いたことは有る。
1998 年頃の自動車制御とか携帯電話とかの話なんで、
コンパイラの規格準拠具合もそれほどあてにできなかった時代の話だけど。 数年前に触ったdspは1byte32bitだったなー >>455
実行ファイル本体はさほど大きくないじゃん。
一番大きいのは cc1.exe か……。
これって必要? >>468
例えばmemcpyの各プラットフォームごとに向けた最適化(の元のソース)はお前がここで言うようなUBだらけだろうし
boostなんかも各プラットフォーム向けに分けて書かれてる部分が多い
そこまでUBを避けてどんなプラットフォームでも動くように、なんてのもYAGNIの一種だと思うけどね >>470
ガチな組込みって言うか普通の企業なら開発環境も決め打ちで作ってテストする >>445 > それを言うなら1byte=8bitsとも限らないんで
>>447 > 1 バイトが 8 ビットじゃないアーキテクチャ (で主要 C++ コンパイラがサポートしている環境) が有るんかね?
>>471 > 数年前に触ったdspは1byte32bitだったなー
1byteは8bitと決まってるんですけど… 2008年に一応はっきり決まったらしいね
ただしC++ではそうと決めてはいないので一応UB >>473
たぶん根本的なところで他人の発言が理解できてない
言いたいことはわかるけど、もはや議論になってないから黙ってろ >>473
各プラットフォームに「対応」できてるなら別にいいんじゃね。
union の未定義がどうこう言ってるのは >>365 程度のことに
あえて各プラットフォームの事情を持ち込むのは割に合わない (そのくらい UB の厄介さには重みがある)
って話題だと俺は理解してる。
ターゲットが完全に固定されてたとしてもコンパイラが吐くコードを把握する自信は俺はないし
たぶん >>468 もないし、 >>473 だって出来れば避けて通りたくない?
その上でどうしてもいじらないといけないくらい速度に厳しい場面とかだったら嫌々やるかもしれないけど、
最初からはやらないって程度の話。 早すぎる最適化は諸悪の根源っていうし。 >>475
少なくとも C/C++ では決まってない。
>>477
対応する大きさの型の別名として定義される。
その大きさの型が存在しない場合は定義されるべきではないことになっている。
無ければコンパイルエラーになるだけなんで本当に 8bit キッカリであることが大切なら
uint8_t を使うべきだけれど、「1 バイト」という意味で uint8_t を使っちゃうと C++ の仕様に厳密な意味では
十分に汎用的であるとは言い難い。
ま、そんな環境はあんまりないんだけど組み込み環境だとたまにあるっぽい。
>>479
UB ではなく処理系定義というべき >>480-481
あのさ、一応UBってことはすぐ指摘されて本人もわかってんだよ、質問者もとっくに見てるはず
>>407辺りから意味無くマウント取るような言い方する奴(はちみつ含む)が出たから荒れてんだろ
そこまで言うなら今現在存在する環境でunionによるtype punningが出来ない環境を挙げてみろ
おそらくどこかにはあるんだろうが、1byte=8bitでない環境はすでに挙げられてるのにunionの方は全く例が出て来ない
>>480
理解出来てないのはお前だ >>482
> 少なくとも C/C++ では決まってない。
決まっていないという根拠よろしく >>483
UBだってことは分かってる、ぼくは>>407でカチンときて怒ってるだけだ、ってことだろ。もうただの口喧嘩でこれ以上何も議論することは無いんだからさっさと終わりにしなよ。 お前もたいがい煽ってると思うが
>終わりにしなよ
俺に言うなよ >>485
傍から低能丸出しのレスかよ…
何を馬鹿にしてるのかもわかってないだろw >>483
> そこまで言うなら今現在存在する環境でunionによるtype punningが出来ない環境を挙げてみろ
↓こういう例は把握してるの? >>405 みたいな理解だとこんなコードもエイリアス有効という話になっちゃいそうで危ないと思う。
https://wandbox.org/permlink/qrUVwDZbNPRnOQyN
#include <stdio.h>
#include <stdint.h>
int f(uint16_t* u16, uint32_t* u32) { *u16 = 0x1111; *u32 = 0x22222222; return *u16 + *u32; }
union U { uint16_t u16; uint32_t u32; };
int main() { union U u; printf("%08x\n", f(&u.u16, &u.u32)); }
出力 (gcc 9.2.0 -O2):
22223333 >>483
実際に有るか無いかなんて知らんよ。
俺は検証するのが割に合わんから可能なら避けるし、 >>365 程度のことに「あえて」使いたいという気持ちはわからんと言ってる。
俺は何がなんでも UB は絶対にダメなんてことは書いてないし、十分に検証できてるものにまで文句は付けんよ。 >>484
- std::uint8_t は cstdint にある。 (C++17 の 21.4.1)
- cstdint は C 標準ライブラリヘッダの stdint.h と同じように全ての型とマクロを定義する (同上)
- C++17 が参照する C の規格とは C11 (ISO/IEC 9899:2011) である (C++17 の 2)
- uintN_t はオプショナルだが 8, 16, 32, 64 については対応する型が存在するなら提供しなければならない (C11 の 7.20.1.1)
- char が 8bit ならば C++ には uint8_t は必ず存在するはずだがオプショナルであると言ってるから 8bit の型がない (char が 8bit ではない) ことは想定内なんだろう
というのが根拠。 >>489
strict aliasing rulesに対する違反にまで話広げてるんだろうけど
さすがにそこまで擁護する気は無いし自己責任じゃないの
そこまで悪質なコードになると話違ってくる
>>490
いやいや、一般的な環境で>>396みたいなのは検証するまでもないから
だいたい昔は未定義だったのが最近の仕様で変わったのもあるだろ >>493
検証するまでもないという確信を持てる程度に (その現場か個人の経験として) 実績があるってことでしょ。
本当に何もないところで確信を持ってるんだったらそれはそれで駄目だと思う。 >>467
> どうせunion使わないためにポインタのキャストとかだろくっだらねえ
アウト
なぜunion使うかの前提すら理解してない >>472
必要ないファイルを削ったら3MBになった。ありがとう。 ちなみに>>489の例はunionじゃなくて同じ変数を指すポインタ渡しても同じことになるからね >>483
> そこまで言うなら今現在存在する環境でunionによるtype punningが出来ない環境を挙げてみろ
今時点では知らないしないだろうな
でも今後もそうなのかはわからない
1byteの定義なんかは処理系がターゲットcpuごとに決めるもの
エンディアンとかも
これは問題視されない
unionに関しては、そういう類いではないだろう
理由は把握してないけど、非podの場合を含めて意味論が決められない、
あるいはaliasingに関係して明確に使うなということなのかもしれない
あえてcと非互換にしているわけで、グレーであることは知っておくべき
ちなみに20からpodという文言が消えると聞いた
さらにcとの乖離が進むのかもしれない POD=trivial&&standard-layout
ってC++11の時に整理済みでしょ
概念は消えないよ バグじゃないぞ
これがバグだったら最適化にかなりの制限がかかってしまう
strict aliasing ruleでググれ >>503
最適化しない場合とした場合とで結果が変わってくるのは駄目な最適化。 だからググれって
鬼の首を取ったかのように叩く奴が出てくる前に教えてやってんのにw >>499
肝心なことが漏れてた。 すまぬ。
C++17 だと 4.4 の脚注に
> The number of bits in a byte is reported by the macro CHAR_BIT in the header <climits>
とあって、バイトとは char の大きさのことだというのが C++ での考え方だと思っていい。
C11 だと 5.2.4.2.1 の CHAR_BIT の説明のところに
> Their implementation-defined values shall be equal or greater in agnitude
> (absolute value) to those shown, with the same sign.
>
> - number of bits for smallest object that is not a bit-field (byte)
> CHAR_BIT 8
という言い回しがあって、 CHAR_BIT は 8 以上であればいい (8 キッカリとは限らない) と解釈できる。
それと、ポインタを持てる単位がバイトだということが示唆されているとも言える。 >>491
charのbit数は決まってないが、バイトはコンピュータ用語として8バイトと決まっているはず。 >>506
多分、
「The number of bits in a byte is reported by the macro CHAR_BIT in the header <climits>」
は、書き間違いで、正しくは、
The number of bits in a char is reported by the macro CHAR_BIT in the header <climits>
だと思われる。 >>507
そうか、歴史的には、byteが7bitだったこともあったんだね。 >>507
これな。
https://ja.wikipedia.org/wiki/IEC_80000-13
C++ が参照規格として示してないので採用してないんでしょ。
まあそんなこと言ったら英単語の意味だってどうとでもとりようがあったりするからアレだけど、
あらためて C++ の規格の中でバイトについて書いてある以上は C++ 世界では
「コンピュータ用語としてのバイト」を採用してないと解釈するのが自然。
将来的には変更されることもあるかもしれんけども。
>>508
C++20 のドラフトでもそのままなので本気で間違ってると思うなら指摘してあげればいいんじゃね?
>>509
9bit のマシンもあったらしいよ。
https://ja.wikipedia.org/wiki/ACOS-6 >>501
概念消えるとは言ってないけど
今回文言消す理由ってなんなの?
何も知らずに口挟むとは思えないから質問させてくれ trivialは生成解体の話で、standard-layoutはデータ配置の話だから
PODってのはレイヤーの違う性質が混ざってて規格に使う用語としては筋悪なんですわ >>510
>C++20 のドラフトでもそのままなので本気で間違ってると思うなら指摘してあげればいいんじゃね?
annotated C++ reference manual, 3.2.1c Integral Limits には、
CHAR_BIT 8 maximum bits in a byte
とあった。 >>514
ANSI/ISO, Standard C プログラマーズ リファレンス
P.J. Plauger / Jim Brodie, 日本語訳, ASCII
第一部 第一章 基本整数型 には、
--------------------------------------------------------
表記, 最小範囲, 表現における制限
--------------------------------------------------------
char, [0,128), signed char か unsigned char のどちらかと等しい。
signed char, (-128,128), 少なくとも 8bit 精度の符号付整数
unsigned char, [0, 256), signed charと同じサイズ。負の数は無い。
--------------------------------------------------------
第二部 第二章 標準ヘッダ <limit.h> には、
--------------------------------------------------------
CHAR_BIT
#define CHAR_BIT <#if 式 ≧ 8>
このマクロは、char 型のデータオブジェクトを表現するのに使われているビット数の最大値と置き換わる。
--------------------------------------------------------
とある。
後半は >>514 とは異なり、byte ではなく、char となっている。 type punning について、このスレで議論されていた union の場合は、「適合コード」の例とされている:
https://www.jpcert.or.jp/m/sc-rules/c-exp39-c.html
適合コード
以下のコード例では、オブジェクトの有効な型と互換性のある型を持つ union 型を使用している。
union {
short a[2];
int i;
} u;
u.a[0]=0x1111;
u.a[1]=0x1111;
u.i = 0x22222222;
printf("%x %x\n", u.a[0], u.a[1]);
このコード例では確実に "2222 2222" と出力される。 >>517
Finally, one of the changes from C90 to C99 was to remove any restriction on accessing one member of a union when the last store was to a different one.
The rationale was that the behaviour would then depend on the representations of the values.
Since this point is often misunderstood, it might well be worth making it clear in the Standard.
[...]
To address the issue about "type punning", attach a new footnote 78a to the words "named member" in 6.5.2.3#3: 78a
If the member used to access the contents of a union object is not the same as the member last used to store a value in the object,
the appropriate part of the object representation of the value is reinterpreted as an object representation in the new type as described in 6.2.6 (a process sometimes called "type punning").
This might be a trap representation. >>520
仕様書が間違ってると思ってる (>>508) からじゃね。 C++は間違っているからな
間違いで間違いを正すことはできな
い まあc++の仕様を完全に守ってる実装なんて一つもないしな。
それ確かめるのに工数かかるってどうなん?とは思う。 >>526
実際には、あれは普通の解説書ではなく、コンパイラを実装する人が重宝するようなバッカス記法や決定性オートマトンなどを使って仕様がかなり厳密に書かれた特殊な本。 >>515
古い C では違ったのかもしれないと思って
念のために C89 も確認してみたけどそのときから >>506 と同じ文言になってるぞ。
C (の公式な仕様) では最初からバイトとは char の大きさのことと結論していい。
K&R 第二版の日本語訳の付録Bだとバイトとは書いていない。
あくまでも要約だから省略したのかもしれないし、
前書きには「予備版 (ドラフトのこと?) が出ていたので早く出せた」という意味のことが書いてあるので、
仕様の決定稿が出る前の一時期にはバイトとは記述してなかった (それを元に本にした) 可能性はあるのかもね。 C/C++ の仕様が信用ならんなと思うのは欠陥報告 (Defect Report) の存在だな。
仕様書に書いてないことの確認がとれていても仕様にないとは言い切れない。
把握できるわけないだろ! 公文書だかんな
はい発表しましたよ、周知義務よろしく
↑
こういう体質なのは今さら驚いても始まらん 公文書なら著作権法による保護が及ばないのでそれはそれで利点があるんだけどな。
実際には ISO は民間組織だし、正式な規格票はクソ高価すぎる。
私はドラフトと cpprefjp しか見てないんだけど、買った人いる? VS2019 の limits.h のコメントはこうなっている :
#define CHAR_BIT 8 // number of bits in a char CHAR_BIT なのに本当に「number of bits in a byte」が厳密定義なら、何らかの説明が欲しい所ではある。
ただ、C言語では、charは言語が扱える整数の「最小単位(?)」などと書かれている文書を見たことがある。
だとすれば、Cに高級アセンブラの地位を期待する需要が有る以上、charのbit数がbyteと一致する必要は必ずあるとは思う。
総合的に考えれば、C言語においては、char=byte でなくてはならず、もはやbyteも絶対に8BITでなければならないので
char、byteがいずれも8bit
であることは事実上、必須である。 Wikipediaの「整数型」のところで、C言語では、何があろうとsizeof(char)は必ず1になると決められており、たとえ16BITワード単位のアーキテクチャでも、CHAR_BIT は 16になるが、sizeof(char)は必ず1になるのだそうだ。
一方、sizeof(X)は、Xの「バイト数」だとされているわけだけど、はっきりいってこんな状況では総合的に考えて、charを8BIT以外には出来ない。 >>536
Rationale の 6.5.3.4 に記述がある。
http://www.open-std.org/jtc1/sc22/wg14/www/C99RationaleV5.10.pdf
sizeof(char) は 1 を返す。
たとえこの単位が 36bit 幅であっても。
C 用語の「バイト」はストレージの最小単位であることを意味する。 >>536
>C言語では、charは言語が扱える整数の「最小単位(?)」
は、>>506 の以下の部分にも書いてあるようだ。
CHAR_BIT とは、
「bit-field以外で最小のオブジェクトのbit数(byte)」
だと:
>C11 だと 5.2.4.2.1 の CHAR_BIT の説明のところに
>> - number of bits for smallest object that is not a bit-field (byte) ポインタを作れる単位を最小単位にするのは理に適ってるんじゃないの。 「bit-field以外のオブジェクトの最小単位」
なわけだから、ポインタが指しうるアドレスの最小単位でもあるわけだ。
言葉が変かも知れないが。 気にするような環境にない奴に限ってこういうこと気にするのな。 個人的には、ソース配布してダウンロードした人が各自勝手にコンパイルするようにするようなプログラムを書いたことが無い。
必ずバイナリレベルでテストして十分デバッグ済みだと思ってからバイナリを配布してきたから。
ソース配布文化は別世界。 だから何だ
結局何が言いたいんだ
規格が間違ってるって言うならISOのWGに意見書出せよ
情報は歓迎だぞ >>537
byteは16bitになる可能性を自分で示しているじゃないか。
一体何と矛盾してるんだ? >>536
C,C++ はそれぞれずっと前から "byte" を独自定義していて、 2008 年発行の IEC 80000-13 の定義は関係ないんだよ。
(・・・って >507 に書いてあったわ。なんでまだこんなこと言ってるのこの人?) byteが何者かわからんから、オクテットとか言う呼び方があるのだろう nibble != 4bits ということはあるのかね >>550
どこかに正式な定義があるかはわからんけど、
Byte の語源は Bite (噛みつく) らしいし、
それよりは控えめってニュアンスは感じるよね。 c++初心者です
実際現場でよく使われる関数はどんなものがありますか? begin, end, operator ++, operator != >>553はSTLしか使ったことないアマチュアの発言 STLだと? 俺はrange-based-forを想定して書いたんだが、気が付かなかったのか? c++11でregexの正規表現で\sと\Sがエラーになるけど、
全部自分で記述で[ \t\r\n]とかしないといけないですかね? >>552
関数セットとしては、やはり伝統的なCのものを使うことが多いんではなかろうか。
ソートや乱数、最大最小値計算、正規表現なんかはC++風のものが好まれる傾向が出始めてるかもしれない。
文字列の一致テストなども、個人的にはCのstrcmp()、_strcmpi()、strncmp()、memcmp() なども結構使ってるけど、若い人の間では std::string の比較機能が好まれているかもしれない。
というかC++から勉強した場合、それしか知らないだけかも知れないが。
文字列表示は、ネットではなぜか cout 系で、cout << "Hello"; のようなものを良くかけるが、
表示する際の16進数と10進数の区別や、表示桁数の指定、float/double値の有効数字桁数の指定、先頭に0を付けるかどうかなどを指定し易いので、古いと言われようが個人的には昔ながらのprintf()が好きだ。 マニピュレータを作ることが出来るのでストリームを使ってるだけでは。 若い子は馬鹿なのでストリームを好むキリッって風に見えるのだろか。 C++の文字列比較で比較開始位置や最大長さを指定したい場合、
if ( str1.compare(0, 5, "abcdefghijklmn") == 0 )
のように書く必要があるが、Cのstrncmp()だと
if ( strncmp(pszText1, pszText2, 5) == 0 )
と書ける。
後者の方が、比較する2つの文字列1, 文字列2の間にみごとな「対称性」があってとても美しい。
さらに、
C :
if ( strcmp(pszText1, pszText2) == 0 ) // 長さ指定なしの全体比較
if ( strncmp(pszText1, pszText2, 5) == 0 ) // 最大長さ指定有り。
C++のstd::string :
if ( str1 == str2 ) // 長さ指定なしの全体比較
if ( str1.compare(0, 5, str2) == 0 ) // 最大長さ指定有り。
のように、長さ指定が無い場合と有る場合の「対称性」もCの方が高い。
さらに、開始位置と長さを指定する引数の位置が、コンストラクタに置いては
std::string str2("Hello World");
std::string str1(str2, 長さ);
std::string str1(str2, 開始位置, 長さ);
なのに、比較においては
str1.compare(開始位置, 長さ, str2)
のように前後が逆転していて、ここでもまた、STLの文字列操作には「対称性」が無い。
なお、MFCのCStringの場合は、
CString str1, str2;
に対し、以下のように strcmp(), strncmp() に簡単に指定できる :
if ( str1 == str2 ) // 長さ指定なしの全体比較
if ( strcmp(str1, str2) == 0 ) // 長さ指定なしの全体比較
if ( strncmp(str1, str2, 5) == 0 ) // 最大長さ指定有り。
一方、std::string の場合、const char* 型への暗黙変換が出来ず、str.c_str() のように書かないといけないという困った問題がある「かも」知れない。
今のC++でどうなったかは知らない。 >>552
人による。
そして上のやり取りでもわかる通り玄人ぶったバカが変な思想を押し付けてくるが
気にしなくてもよい。 >>561
そんなん好きなようにラッパー関数を書けばええがな。 >>558
ストリームよりprintfがましってのは同意だがprintfよりfmt使え
C++20から標準になる >>565
気になるので言っておく。
stream 入出力とは、古くから FILE, fopen, fclose, fgetc, fread などに対して使われていた言葉で、cout/cin 系専用の言葉ではない。
なんでもそうだが、言葉は有名なところで先に使っていた方が優先されるべきだ。 >>566
1. Cのstdin, stdout, FILE, fopen, fclose, fgetc, fread 系の関数群のことは、
非常に古くから「Stream I/O」と呼ばれていた。
2. C++ では、「iostream」というような名称で cout/cin 系のクラスが定義された。
後者の事を単に「ストリーム」と言っても1とは区別が付かないのでやめて欲しい。 >>556
おい554、range-based-forはコア言語だぞ、断じてSTLではない
そもそも規格票に一言も出てこない用語でイキッてんなよ
俺がアマチュアかどうかも証拠持ってるわけねえよな
寝言は寝て言えタコ助 >>567
C++スレなので。
コンテキストで十分判別がつきます。 何を使ってもいいけど、レイヤは切り分けた方がいいと思う。
string を使ってるときは char の配列と混同させて使うべきではないし、
char 配列を使っているなら string のことは忘れた方がいい。
どこがレイヤの境界なのかはっきりさせて。 >>565
初めて聞いたが、書式で{1}{2}など C#に似た使い方が出来るが、
逆に、{ や } の記号を簡単にはかけなくなり printf より使いにくくなってしまう。
しかも、{1}{2}が使い易いとは思わない。むしろ%sや%dより混乱する気がする。
しかも標準ライブラリではない。 >>569
付かない。
C++はCを前提にしているのだから、両者を混在して使うのが普通だし。 >>570
仕組みを深く理解していれば混在させても問題もない。
文字列程度でレイヤー訳が必要になるんなら、Cの上位互換の名を外すべきだ。
別の言語としてやり直せ。 >>572
もうそんな時代じゃないので。
いまは、CがC++に依存する時代。
C++で書かれたAPIをCから呼び出す。
C++がスクリプト言語のような柔軟性を持ちつつ、しかしシステム言語として使われるのは、Cから呼び出せるからでは。 c++がスクリプト言語のような柔軟性をもつ?何言ってんの?病気か? >>568
言い返すとこはそこでいいのか?w
ちなrange-based forはまだC++に慣れてない初心者に押し付けるほどのものではないし
ましてrange-basedに合わせるためにoperatorの実装を押し付けるのは論外
ドヤりたいだけの初心者は黙ってろマジ迷惑だから >>574
coutやstd::stringが使い易いなら誰もCでやろうとは思わないが、現実にはCの方が便利だから
あくまでも使いにくいそれらを使おうとするとのは、今のネットは新しい情報だけが上に来てしまうため、C++しか知らない人が多いためだ。 >>571
好きにどうぞ
時代に取り残されないようにな >>577
一行目の「だから」の直後に「。」が抜けていた。 >>578
古いものを知らないで勝手に変な仕様を入れてしまう人が増えているんだ。
C#やcppfmtのそれは、PerlやRubyよりも遥かに使いにくい。 >>580
好きにどうぞ
時代に取り残されないようにな >>576
現場でよく使われる関数は何かと尋ねられて
すぐ思い当たるものを正直に述べたのが
初心者に押しつけたように見えるのは
おまえの目か頭のどちらかがおかしいからだ
いや両方か?
C++11に付いていけず置いてかれ
C++03でドヤりたいだけなアウトカーストこそ
マトモな初心者に触るなアホが伝染るから マジでプロでもフリーソフト開発してるアマチュアでもいいから実際の開発に使ってる人(と初心者)専用の相談スレがあった方がいいかもな
開発全くしてない人間でも別に好きにすればいいが、ここはプロや経験長い人にマウント取りたいだけのクソバカが多過ぎる(しかもそれに初心者が騙されて右往左往する)
まぁその役割は初心者スレがすでにある程度担ってんだろうけど >>582
アマチュアで初心者でドヤりたいだけ、ってのは否定しないのかwwww >>584
はあ? 俺がアマチュアという事実無根の誹謗中傷をしたことを否定しないのはおまえだろ 嘘つき野郎と日本語で言っても非難の度合いが弱すぎるので英語でLIAR!! 仕様に「任意の」とついたら、もうCでは拷問になる。
CIA真っ青級の。 めんどくさいからそろそろ天才がどうたらいういつもの結論行って。 Networking TSが入れば追いついてこれるものなど居ない。 江添に影響されたバカが増えたよな。
ああいうまともにコード書いてないで知ったかするカス態度はほんと害悪だわ。 生データからノイズを除去し有益な情報だけを抽出できないやつに江添の文面は無理 まぁC++専門のライター自身がC++に変な幻想抱いてるしね
スクリプト言語の代わりになったって仕方ないのに
むしろC++にそのように振る舞わせるためにユーザーがアホほどコスト掛けなきゃいけなくなるという ただ新しい言語をなぜやるかの理由の一つとして
年上にマウントとるためってのは実際大きいんだろうなと思う。
これは他言語でもそうだし、昔からそう。
この点についてこの業界は50年以上全く解決されてない。 C++でワンライナー書けるようになったら、初心者脱出。 >>574
cがc++に依存するって何のこと言ってる? 俺が6800のマシン語やり始めた頃
ジジイたちはPCなんてオモチャとバカにしてたから
マウント取りたきゃいつでも取れてたが
そんなパンピーが考えそうなくだらねえことには興味なかった >>594
時代がどうこう言ってたのに03までやんけ(´・ω・`)
>>598
老g(ry 君そのマウント癖やめた方がいいよ
しょっちゅう恥かいてるだろ?
しかも自爆でw いや、CINTなんていにしえの遺物で、話題になることも無いし。
そこで気づいてほしかったのだが。 API呼び出したら、中身はC++で書かれてるだろ? >>557
エラーってのがコンパイルエラーなら"\\s"とかR"(\s)"にする、実行時ならコンパイラのバージョンを上げる、でどうかな その理論だとc++もcでかかれたコード呼ぶだろ
ライブラリがc++のしか用意されてないとかそういう話かと思った >>609
Cから呼び出されるC++関数を書くにはC++側でCに合わせる必要がある
そういうのをCがC++に依存したというのはちょっと無理あるだろ >>609
時代とか大口叩いたくせに後で矮小化すんなよ、くそださい
その例でいうと中の実装言語が何かはc側は関知してないだろ
それはcがc++に依存とは言わない
その関数が提供する機能に依存してるという特定の事例にすぎない
だいたいABIは事実上cベースしかない
c++がcのふりしてるんだよ >>609
・Windowsの場合、C++のプログラムは最終的には、Win32を呼び出しているが、 Win32は、記述言語もインターフェースもC。
・Linuxでも同様。LinuxのKernel本体はCで書かれている。
GTKやKDE, Qt は原則 C++ だが、最終的には Cで書かれ、かつ、Cのインターフェース を持つ System Call が呼び出される。
どちらも
C++ ---> C
の流れ。基礎部分やバックエンド部分は C になることが多い。
逆に C から C++ を呼び出すことは稀。
だから、事実とは逆。 >>614
gccのマングリング化法は資料がある。
vc++も解析資料がある。
clangはgccのマングリング化法を使っている。
しかし、gccのマングリング化法を使うと、gnu/FSF/GPL 信者から
「真似をした、ずるい」と文句を言われたり、証拠もないのに
「勝手にソースを使った」などと風評被害があるに決まってるから
使いづらい。 windowsはc++と混在してたはずよ
win32だけは違うとかあるかも試練が >>617
・GDI+ は C++ インターフェースだが、内部では Cの API を呼び出す仕組みになっている。
・DirectXも C++ インターフェースではあるが、COMだから Cからも呼び出せる。 >>617
Win32は、GDI+以外はほぼ全て Cのはず。
MFCは、Win32をラッピングしているから、
C++(フロントエンド) ---> C(バックエンド)
の流れ。 こいつらextern "C"についてさえまともに理解してなさげ。。 >>608
Cだけだと、少し不便なだけで完結する。
むしろ、C++ だけではスクリプト言語的なことしかできないので、完結とはいいがたい。
このスレは新しい言語である C++ をネットで学んだだけで、基礎となる C の部分が学べてない人が多いようだ。
ネットだと新しく入った機能や新しい記事だけが上位に来てしまうから、新しいことしか知らない人が書いたページだけしか見る機会がなくなってしまうが、それだと悪循環になり、古くてももっと良いものがあっても学べない。 C++を使いこなせない老害がCに固執してると見た。 このスレに限らず、検索してても初心者が過去の遺物だのオワコンだの死すべしだの
口の悪い厨二病発言するだけで上級者になったつもりのクソブログばっかり上に出るからなぁ
ABIというかマングリングとかバイナリ周りの統一に関しては、C++はいつまで経ってもCの後塵を拝する形になってるんだが、何年かC++やっててもその程度の欠点にも気付かない奴ってのは
要するにそういうことだろ・・・ Cで出来ることはC++でもできる。
C++で出来ることがCには出来ない。
Cは老害。 あんま調べてないけどモジュールも多分ソースコードレベルでのヘッダ依存の解消のためであって
ライブラリファイルみたいな外部に出す方法はまだまだ来ないだろうし >>624
C++はCのサブセットなので、当然それは正しいことなのだが、
このスレの人達は、「C++のうちからCの部分を除外した部分だけ」
をC++だと言い張るので異なるのだ。 >>622
このスレで、Cを使うのを朗がい呼ばわりしている人達を見る限り、単にC++に加わった新機能を解説したサイトをネットで学んだだけで古いC++やCを知らないだけに見える。
確かに、Cより優れているC++の部分を使わないのは老害だ。
しかし、C++より優れているCの部分を使わないのは、単にCを知らないだけ。 >>624
話をそらすな
cがc++に依存してるとか言い出したから
総ツッコミがはいったんだろが
自分で言い出したこと忘れたのか?
それ老害の先の症状だぞ c++より優れているcの機能って言うほど無いだろ
printfとiostreamにしたって好みによるとしか
まあ次の標準に来るから使えるならfmt使っとけ
明らかに上記のどちらよりも優れているから >>629
fmtは{}が直接使えないからだめらしいぞ
しかしprintfの%は気にしないみたいだぞ >>615
インターフェースとか言い出したらWin32APIはPascalやでw >>629
昔BASICが人気があったころ、print と print using の二種類有り、
cout は前者の、printf は後者の流儀と同じである。
初心者は、print から使い始め、慣れてくると print using を使うと言われていた。
後者はとっつきにくいが独特の便利さがあるとされた。
つまり、BASICは、cout 方式も使えたのに、敢えて printf 方式も用意したのだ。
このスレやネットには初心者が多いので、覚えることの少ない coutが好まれているだけ。
なぜcoutが問題なのかと言うと、書く量が多くなることと、見た目的に結果を予想しづらくなるからだ。
printf( "(x, y, z, w)=(%d, %d, %d, %d)\n", x, y, z, w );
で済む所が、coutだと、
cout << "(x, y, z, w)=(" << x << ", " << y << ", " << z << ", " << std::eol;
などとなってしまい、打ち込みにくいだけでなく、結果がどうなるかも直感的に分かりにくい。
出力にカンマや空白を入れるのが難しいのだ。
さらに、これを16進に直したい場合、printf なら、
printf( "(x, y, z, w)=(%X, %X, %X, %X)\n", x, y, z, w );
と僅かな修正だけで済む。さらに、左に0を埋めた8桁の16進数に直したい場合には、
printf( "(x, y, z, w)=(%08X, %08X, %08X, %08X)\n", x, y, z, w );
で済むし、表示に0xを含めたい場合には、
printf( "(x, y, z, w)=(0x%08X, 0x%08X, 0x%08X, 0x%08X)\n", x, y, z, w );
で済む。これで、0x0000ABCD などと表示できる。さらに、0x0000abcd と表示したい場合は、
printf( "(x, y, z, w)=(0x%08x, 0x%08x, 0x%08x, 0x%08x)\n", x, y, z, w );
で済む。どのような表示形式にしても、コンパクトで見易い。
一方、coutでこれと同じようにしようと思ったら、見易くするためには5行くらいの長さになってしまうだろう。
それでもこのように美しい見た目にはならない。
昔のBASICのprint文にも同じような問題点がおきたから、print using が生み出されたのだ。
それを知らないで、coutがprintfより優れていると思ったら大間違いだ。 >>632
誤: cout << "(x, y, z, w)=(" << x << ", " << y << ", " << z << ", " << std::eol;
正: cout << "(x, y, z, w)=(" << x << ", " << y << ", " << z << ", " << w << ")" << std::eol; >>633
もっと言えば、この cout は、古いN88-BASIC言語より記述量が多い。
<< を使うからだ。N88-BASIC は、<< の部分が ; となる。
N88-BASIC なら、
print "(x, y, z, w)=("; x ; ", " ; y ; ", " ; z ; ", " ; w ; ")" 1. N88-BASIC
print "(x, y, z, w)=("; x ; ", " ; y ; ", " ; z ; ", " ; w ; ")"
2. C
printf( "(x, y, z, w)=(%d, %d, %d, %d)\n", x, y, z, w );
3. C++
cout << "(x, y, z, w)=(" << x << ", " << y << ", " << z << ", " << w << ")" << std::eol;
C++ が最も汚く、書きづらい。
N88-BASIC ---> C の printf() // 進化と言えよう。
N88-BASIC ---> C++ の cout // 後退のように見える。
cout は、classのパワーを例示するために用意されたと聞いている。
もともと実用性は無かったのに、それを知らない人達が使うようになってしまったのが現状である。 printfとcoutの議論はgoogleでもやってたな。
型安全と見やすさのどちらが重要かみたいなやつ。
型安全にこだわるやつはたいてい現実見てないなってのが良くわかる例になってる。 >>635
一見、printf と cout で記述のしやすさに大差ないと思う人もいるかもしれないが、実際に入れてみると coutの記述のしにくさは異常なほどである。
特に問題なのが、後から "," の後ろに空白を入れたくなったりしたときの修正のしにくさである。
printf の場合は、最初の書式付文字列の中にまとまっているので、非常に修正し易く、数秒で修正できてしまう。
ところが cout の場合は、全体に散らばっているので修正箇所を見出すのが非常に難しく、間違いの元になり易い。
全部修正したつもりでも、いくつか入力し忘れていたり、"・・・" の中に入れなければならない所を、"・・・" の直後の「地の文」に入れてしまったりする羽目になる。
また、よくあるのは、" や << を入れ忘れたりすることである。 >>637
coutの場合に、よくあるのが、" の内側と外側の混乱である。
"で文字列を始めたり終えたり何度も繰り返すので、目が混乱して
どっちがどっちか分からなくなる。
コンパイルしたとき、文字列が開きっぱなしになって、酷いときには
ファイルの最後までコンパイルしてしまって、エラーがどこで起きたのかさえ
分からない最悪の間違いを犯してしまう。
だから、perl,ruby,pythonでは、
"#{変数名}"
のような記述が発明された。
これは、printf を進化させたものといえよう。
しかし、coutは退化である。 どんなクラスのオブジェクトでもoperator<<さえ定義すれば吐き出せるのがiostreamのメリットよ
クラスは組込型のように振る舞えるべきだっていうオブジェクト指向の理想のために必要だったんだよ
安全な後世から後出しジャンケンで叩くのはフェアじゃないよ
それはそれとしてiostreamは使いづらいクソだという意見は否定しない >>641
そんな既知の話ここで長々と書かんでいいから
自分のブログでやれ
ここにはリンクだけ張りに来い >>639
中学校が休校になって暇を持て余してるんだろう >>565
ようやく来たかー。
望んていた形そのものだわ
ID:HyVcGvBE
スレによって態度違いすぎw >>636
両立できそうなところへ、どちらかが優れているという結論を目指すという
前提がそもそも間違っている不毛な議論だと思うが >>646
統一したいという輩がいるんだからどっちでもいいとしても
少なくともその輩を黙らす必要はあるだろう。
まあlinusの言う通り馬鹿をプロジェクトに入れないっていうのがやっぱり正解なんだが。 >>574
>C++で書かれたAPIをCから呼び出す。
extern "C"
でもしないかぎり、あり得ないのでは?this とかマングリングとかどうするの? >>583
>マジでプロでもフリーソフト開発してるアマチュアでもいいから実際の開発に使ってる人(と初心者)専用の相談スレがあった方がいいかもな
ここがそうだと思います
そう思えないのであれば、それはスルー力が足りないかと >>648
関数ポインタに生アドレスを渡すとかw
GetProcAddressみたいに
QueryInterfaceと似てるけど、より面倒くさいね >>608
そうでもないですよ
ほかの言語から自由に呼び出せるようにするため、汎用ライブラリをわざわざ C で書いたりするでしょう? >>612
私は extern "C" くらいしか思いつかないですね… >>615
>逆に C から C++ を呼び出すことは稀
というか皆無といういうべきでしょう、extern "C" でもしない限り >>624
>Cで出来ることはC++でもできる。
C++ でできないこともあります
他言語から自由に呼び出せるライブラリを書くときは C で書くしかないでしょうね…
extern "C" というのは、もはや C で書いているのと一緒… >>656
一緒ではないだろ
APIはcで中身はc++ってのは多い
実際おれもそうしてる
c++使いたいからな >>654
あーそうなの?
テンプレートとかムブコンとかうっすらぱーw >>650
>ここがそうだと思います
本気でそう思えるなら自分のことしか見えてないんだろうな
あといちいち分けてレスするな 昔BeOSっていう純粋にC++で書かれたOSがあったけど、コンパイラやAPIのバージョンアップで
マングリング規則やクラスのエクスポート時の互換性が無くなって、
過去のアプリが全く動かなくなったりした(こういうのはBeOS限定の話ではないけど
クラスライブラリの互換性をどうにかするために、MSの場合はvtblが先頭にあることを利用したり
余分な引数を追加したりしてコンパイラ間の互換や後のバージョンアップに対応できるようにしたけど
そもそもvtblを先頭に置くのは規格で決まってるわけではない
上の方でUBUB言ってた人達はこういうのどう思うんだろうね >>610
コンパイル時にエラーが出ていました。
下記でコンパイル通りました。
ありがとうございます。
std::regex re( R"(^\s*(^\S+)\s+(\S+))")
ダブルクォーテーションの内側を全部丸括弧でくくればよくて、そのカッコは
下記の results[1] にはセットされないんですね。
知らないとちょっと戸惑いそうだ。
std::regex_search(word, results, re) >>660
OS の製作元と同じマイクロソフトが提供している VS で COM を作る分には別にいいんじゃないの。
移植性を考える必要もないし。
しかし、こういう変な形でなければ C++ で作ったバイナリは運用しづらいということの証明にもなってはいるよな。 >>660
c++でUBでも処理系が定義してる範囲で、
かつその処理系に依存していいなら問題ないだろ
そのへん区別しろ >>662
いやVS限定ではないはず、他のコンパイラからでも使えるでしょ
>>663
問題かどうかではなくて、そういうトリックを使わなければ達成できない目的があったときどうするの?みたいな話
と、バイナリ関係の規格が全然足りてないよね、という話 >>664
わからんやっちゃな
処理系が決めてる範囲でやるんだよ
実際それでなんとかしてるだろ?
テンプレートでいきってる標準化の連中がバイナリ境界に無関心なのはカスだと思うけどな >>664
まあ実際には VS に合わせてるコンパイラが多いのは知ってる。
gcc とかもデフォルトではビットフィールドの割り当て順序が違ってるんだが、
VS に合わせるオプションとかが用意されてたりもするくらいには Windows では VS が基準。
ただやっぱりそこには「検証の手間」が発生するよ。
VS でやる分にはマイクロソフト自身がやってんだから疑いが入る余地はない、
確実に問題はないという意味で VS に限定して問題ないと表現した。
ひょっとしたら VS 以外のコンパイラでもドキュメントをよく見たらどっかに書いてあるのかもしれんけど、
少なくとも私はそれを確認したことはない。
---
バイナリの規格ってのは「せめて Windows 内では」とかいうレベルのこと?
違うアーキテクチャで統一できないのは仕方ないけど、
主要なアーキテクチャ/OS内ではっきりした規格を定めれていないのはなんでできないんかなぁと思わなくはないな。
うーん、でも Linux なんかだと GCC のマングルが実質的な規格そのものみたいな感じもするし、
Windows だと結局は VS に合わせるしかないんだからそれが規格みたいなもんじゃね?
その規格 (的なもの) に合わせられていないのは単純にやる機運が起こってないだけで。 >>666
マングリングは政治的な問題も絡むのか・・
すまんバイナリって言ったから誤解させたかもしれん、インターフェースの話ね
クラスのエクスポートとか回り道せずに出来るようにならないと、上でも言われてる通りいつまでもCのスタイルに合わせざるを得ない
てかvtblを先頭に置かないコンパイラを知らんのだけど、あったとして合理的な理由とかあるんだろうか どんな状況でも動くことを考えたらCの仕様に行き着く iostreamの使いづらさはboost::formatで大体解決する
ってかformat指定をワザワザprintfから改悪してstreamオブジェクトに余計な状態保持をさせてしまったところ
std::vector<bool>が典型的だけど、初期の頃に考えられた言語デモンストレーションの為に、実用性に疑問の残るおかしな仕様が標準化されちゃっているところがあるよね >>630
printf が関数として、特別な機能を持たせている文字は % の1つだけ。
しかし、言語自体が \ をエスケープ記号として使っているので、合計2つが
特別な意味を持っており、これでも問題になる場合がある。
一方、cppfmt の場合、少なくとも %, {, } の3つが特殊記号になっていて、
\と合わせれば、合計4つもが特別な意味を持っており、いくらなんでも多すぎる。
それがセンスの悪さ、と呼ばれるものである。 >>670
でお前printfで64bitの整数出すのどうしてる?
正直に言ってみな >>672
そうなんだ
でお前はそのお前固有の環境を前提に俺たちに何を語りかけたいのさ?
寂しいからとかやめてよ >>670
pythonっぽいfmt::formatが{}
cっぽいfmt::formatfが%じゃないの?
前者がわざわざ2文字なのは見やすさ重視だからこそだし そうか
じゃあお前だけtime_tに32bit使って2038年問題で苦しめ printfは型と対応するformat指定法を把握していないと簡単にバグるからね
まあ、最近のまともなコンパイラだとprintfのformat解析まで静的にやって殆んどの場面でエラーなり警告なり出すから大分マシだけど (ITドカタの爺さんには)64bitはなんのメリットもない
pythonなんて当然触ったこともない >>675
time_tの問題をコンパイラの64bit化しなくては解決できないほどプログラミング能力がないんだね。
アホみたい。 >>679
自分で自分に批判レスするってアホみたい 知らなくて驚くかもしれないけど、32bitのシステムでも64bit整数は使えるんだよ 64ビットは不要とか言っちゃう奴がC++の仕様に文句言うとかないわw ハード屋が単に食い扶持確保のために用意しただけのものを勝手に意味があると思い込んでいる馬鹿な人達。 >>684
純粋な疑問なんだけど、あなたは4294967295を超える整数を扱う必要がある時にはどうするの? 構造体を知らない人が64ビット言ってるんだと思います。 仕事のセンスだよ
じゃあ構造体使って1兆÷7を計算するコード書いてみてよ
64bit整数を使えば「100000000000ULL/7」だけで済むものを
どれだけ面倒で下らないコードで水増しして生産性下げてチームに迷惑かけてるのか興味あるからさ 64bit機のNintendo64は32bit機のプレステ1に負けたよね。商業的に。 知らないから君の最強の多倍長整数64bit計算を見せてよ というか構造体じゃなくて配列でいいよね
uint32_t trillion[2] = {232, 3567587328};
を7で割るコードを見せてください
64bit整数の割り算をわざわざ多倍長整数でやるなんてそんな無意味なコード書いたこともないから知らないんだよね
見本見せてよ
「100000000000ULL/7」よりもずっと優れてるんでしょ? 構造体を学んでください。
いま素晴らしいアドバイスを与えましたよ? じゃあ構造体でいいよ
struct Int64 {uint32_t high, low;};
Int64 trillion = {232, 3567587328};
さっさと7で割れや
逃げるのか? いや全然ダメ。
構造体の何たるかが全然わかっていない。
まともな師匠に師事して学ぶべきです。 しょうがねえな
多倍長の除算を書くのが面倒なんだったら、>>695>>697にはわざと32bit環境での多倍長演算には適さない
問題のある表現使ってやったからそのことを指摘するだけでもいいよ
それすら出来ないならお前こそまともな師匠に師事して出直してこい え、マジ?>>695>>697の何がダメか本当にわかんないの?
相手して損した 構造体を知らないものが64ビットを愛好するということが分かった。 >>661
R"..." はいわゆる生文字リテラルでWindowsのファイルパスとか正規表現文字列を書き易くするための機能やね
ただ無駄に高機能で
R"***(文字列中)")***" ⇒ 文字列中)"
なんてのも指定できるけど個人的にはやりすぎとしか思えない
https://cpprefjp.github.io/lang/cpp11/raw_string_literals.html そもそも暗号系扱うならそんな長さじゃ全然足らんしね。
構造体構造体言ってる奴もそれわかってなさそうだが。 プログラムが実際にかかった時間とCPU時間の2つを最後に表示させるのに何か関数用意されてますか?
clock()はCPU時間だけですよね? >>703
それ必須(syntaxはさておき)
それなしのrawは片手落ちだよ >>706
clock()つかってんならtime()使えばいいじゃん
ちなみに君c++使えてる? >>699
この爺さんたぶん足し算引き算繰り返すんだよ
それならcarry bitだけ気にすればいいからね
32bitの乗算の結果は最大64bitだから爺さんの能力オーバーする >>707
それおまえさんの個人的意見だよね?
俺はPythonとかC#あたりでいいと思ってるだけの話
必須でもなんでもないよ >>710
意見でもあるし、定性的にそうだよ
閉じカッコを含められない制限に何か合理性ある?
ptyonだってトリプルクォートとかrawとか建て増しになってとっちらかってるわけで >>711-712
> 閉じカッコを含められない制限に何か合理性ある?
生文字列中にダブルクォーテーションを含めたい機会がどんだけあるんだ?
って話な
Pythonなら R"ABC" "¥"" "def" ってやるだけ(R'ABC"DEF' でもいいけど両方含む場合はとか言い出すだろうからw)
C# なら @"ABC""DEF" でできる
> ptyonだってトリプルクォートとかrawとか建て増しになってとっちらかってるわけで
トリプルクォートとRaw文字列は役割違うし別にとっちらかってないけど? ダブルクォート含みのCSVとかをパースするための正規表現書く時とかいくらでもあるけど
raw文字列ってそういう時のための物じゃないの? >>713
> トリプルクォートとRaw文字列は役割違うし別にとっちらかってないけど?
それこそお前の感想だよね?w
役割が違う言えば聞こえがいいが、pythonの文字列リテラルは機能の直行性もない短絡的な設計
rawは短い正規表現などの用途しか考えてなくて複数行でかつエスケープなしができない
でそういうのが欲しいケースはいくらでもある
JSONを文字列で埋め込んでおきたい場合とかね
c++のrawは建て増しなのは同じだけど設計の筋は通ってる
ただもう一歩がんばってindent合わせが可能な仕様にしてほしかったな >Pythonなら R"ABC" "¥"" "def" ってやるだけ
rawの意味ねぇなww >>690
だから、64BITの時間をそのまま7で割らなくてはならないような状況に
なってしまうあなたの数学力が足りない。 >>717
それから、本当に桁数の多い数の割り算計算が本質的に必要な場合は多倍長計算ライブラリを使えばいい。
多くのアプリではそういう状況が少ないと言うことだ。
科学技術計算では、doubleか、4倍精度float数を扱えればいいので、64BIT整数が必要な場面は今のところ少ない。
メッシュの個数やループ回数が32BITを超えるようなものは、今のCPUでは重過ぎて普通、計算できない。 >>717
64bitの時間? おまえさんもしかして、2922億年のことを言っているのか?
64bitの1秒であろうと32bitの1秒であろうと1秒は1秒でしかないんだが >>715
> rawは短い正規表現などの用途しか考えてなくて複数行でかつエスケープなしができない
まさかと思うがトリプルクォートとRaw文字列を組合せて使えることも知らんのか?
そんな知識で直行性とか語るなよw >>716
まああんまり無いケースだから多少見辛いのはしゃーない
C#みたいな方がまだマシだとは思うが 業界全体の傾向では「printfへの回帰」が見られる
fmtはprintfの21世紀型強化版として捉える
つまり、+や<<で連結するのはどの言語でも煩わしかった
だからprintf(のようなもの)に戻ってきている
CUIやテキストへの出力はprintf程度で充分だった、と誰もが気付いた 複数行できるぞ
std::cout << R"(abc)"
R"(def)"
"\nghi" << std::endl;
しかもエスケープあり/なしを途中で切り替えることまでできる 普通は16ビットあれば十分ですよ。
64ビット厨はプログラムしたことあるの? >>718
へー
お前の世界の普通の会計ソフトは43億円を扱えないし
お前の世界の普通の防犯カメラは43億ミリ秒(たった5日)連続稼働したら落ちるし
お前の世界の普通のOSは4GBのファイルを作れないのか
アホくさ >>726
16BIT時代から一兆円は扱えた。
Z80 はマシン語としては整数の掛け算/割り算も浮動小数点も全くサポートしてなかったが、BASIC言語ではどれも普通に出来た。
同様に、32BIT CPUでも、64BIT整数が扱えないわけではない。 >>720
まじか・・・正直その組み合わせ気づいてなかったわ
ただやはりpythonはエスケープフリーで任意の文字を含められない点で機能が不完全 pythonは文字列まわりがとっちらかって結局2と3で分裂したが。 python2で混乱してたのはraw周りじゃないぞ
文字列の文法は3でもほとんど変わってないはず
strとunicodeとbyte(に相当するもの)の扱いがナイーブ過ぎてグッチャグチャだったのがpython2の大問題 >>729
pythonでも"と'を同時に使わない限り何でもかけるじゃん。
一方、c++は)"という並びを文字列中にかけない制限があるわけなんで、
もちろん後者のほうか確率は低いけど、pythonを一方的に機能不全と言えるほどじゃないなー >>718
>多倍長計算ライブラリ
GMP が有名どころではありますが、GPL なのが嫌ですね
そういう人のために、かなり遅いのですけれども https://mevius.5ch.net/test/read.cgi/tech/1434079972/51 を公開していますので、よろしければ使ってください >>732
いや書くためにユーザーに指定させるようにしてるんだけど正直そこまでやる価値はあるんか?
って話
理念はわからなくもないけどやりすぎ感半端ない やりたくない奴はやらなきゃいいだけ
この機能はあった方がいい
ないとrawから離れてしまうのは君自身が>713で例示している >>737
嫌なら使わなきゃ良いってか?
PythonなりC#.並の記述ができるならいいけどそうじゃないからねぇ >>51
We regret to inform you that we are shutting down code.hackerearth.com.
Apologies for any inconvenience caused.
Thank you for understanding. >>735
>>739
というエラーが出てページが表示できない。 >>741
症状変わらず。
あなた、試してないよね? >>729
> ただやはりpythonはエスケープフリーで任意の文字を含められない点で機能が不完全
だから前にも書いたけどそんな機会がどんだけあるんだよって話な
ぱっと思いつくのは " や ' を含む正規表現を書きたい時ぐらいだけど毎回そんなものを書かないだろ
めったに無い時のために毎回無駄な ( ) を書かされるのはちょっと嫌
※ 最後の行は個人の見解です すみません、教えてください
JAVAだとinterfaceを定義してsetListner的なことが出来て、リスナー不要なときはnullを指定できます。
C++だとどうかけばいいでしょうか?
interface用のクラスを一つ用意してvirtualメソッドを並べれば出来そうな気がしますが、リスナー不要な時に上位からnullを指定できない気がしていて std::functionが一番簡単だと思いますが。 ありがとうございます。
具体的なコードを教えて頂けないでしょうか?
例えば、適当に拾った以下のJavaコードを例にして同じ事を出来るとC++のサンプルを教えて頂けると参考になります。
続く class HeavyTask {
private TestListener listener;
// interface 設定
interface TestListener {
void onSuccess(int result);
}
// listener
void setListener(TestListener listener) {
this.listener = listener;
}
void taskStart() {
int sum = 1;
int i= 0;
for ( ; i< 20; ){
sum += sum;
i++;
}
if(listener != null) {
// 計算が終わったら結果をlistenerに渡す
listener.onSuccess(sum);
}
}
} すみません、簡単な例でいいので、リスナー登録してそこから複数のメソッドがイベント毎に呼ばれるようにする方法がしりたいです。。 std::functionは関数っぽいものなら何でも突っ込めるので、好きなようにお使いくださいとしか。
本当は出来ないんだろ?とか煽ればだれか書いてくれるかも。 最初に自分がいってるとおりじゃないんか
インターフェイスの派生クラスのポインタ渡せばいいだけで
不要なら0入れて呼ぶときにチェックするだけじゃないの てか、C++でもほとんど>>748と同じようなコードになるだろ 具体的にfuntionを使って、リスナーをnewして呼び出すあたりとかコードがみたいです。。virtualだと誰かが継承してクラス化しないとだめですよね?
Javaのように、setListenerの引数にリスナーだけnewしてしていとか、null指定とかする方法がやっぱりよくわからないです。 クラス化してポインタで管理するだけ
javaみたくnewでそのままオーバーライドはできないと思う
やりようあるんかな すみませんが、これでお願いします。
C++のfunctionを利用して、一番スマートな感じなコードを教えてください。
m(__)m
続く↓ // 上位からやりたいこと
class Main {
Test test = new Test();
test.setListener(null); // callback不要な時はnullを指定したい
// callbackが欲しい時はこんな感じで登録したい
test.setListener(new Test.TestListener() {
@Override
onSuccess(int result) {
System.out.println(result);
}
@Override
onError(int errorCode) {
System.out.println(errorCode);
}
});
test.run();
}
続く↓ // Testの中身の作りはどうでもいいです。
// Main側からTest側が綺麗に呼び出せれば、それに合わせてTest側を作りかえるでOKです。
class Test {
interface TestListener {
void onSuccess(int result);
void onError(int errorCode);
}
private TestListener listener;
void setListener(TestListener listener) {
this.listener = listener;
}
void run() {
if (listener != null) {
listener.onSuccess(0);
listener.onError(1);
}
}
} スペースがちゃんと入ってなく、見づらくて申し訳ないです。
よろしくお願いしますm(__)m こんな自分でやる気のない人にはぜひエサを与えないでほしい。 いや、困ってるみたいだし、書いてやれよ。
俺がケチョンケチョンに添削してやるから。 やる気がないわけではなくて、勉強しているけどどう書くのか分からないだけです。。 C++だと、イメージだけど
test.setListener([](int result)) { print(result); });
みたいにかけそうってのはわかりましたが。。
NULL指定したい時とか複数のoverride対象の
メソッドを並べる書き方とか良く分からず。 class TestListener {
public:
virtual void onSuccess(int result) { }
virtual void onError(int errorCode) { }
}; class Test {
private:
TestListener *m_listener;
public:
Test() : m_listener(NULL) { }
void setListener(TestListener *listener) {
m_listener = listener;
}
void run() {
if (m_listener != NULL) {
m_listener->onSuccess(0);
m_listener->onError(1);
}
}; 式としての匿名クラスはc++には無いよ。
クラス宣言としての無名(?)クラスは書けるけど。
https://ideone.com/SnMj5k class MyListener : public TestListener {
public:
virtual void onSuccess(int result) {
printf("だから何?\n");
}
virtual void onError(int errorCode) {
printf("100年ROMってろ\n");
}
};
Test test;
MyListener lis;
test.setListener(&lis);
test.run(); ありがとうございます。
>>771
Test2がイメージしていたのと近いです。
こんな感じで書くんですね。 >>768
> 複数のoverride対象のメソッドを並べる書き方とか
>>772はこれ↑についてのレスね。
foo.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {}
public void mouseMoved(MouseEvent e) {}
});
きっと↑こーいうのがやりたいんだと思って。 ありがとうございました。
内容は大体理解できたので、今後のテンプレとして使わせていただきます。
助かりました! http://codepad.org/4KkPN9ki
上記を実行すると下記結果になります。
[2]を見ると、vectorの3つ目以降はポインタのアドレスがあうのですが、2つ目までは合っていません。
MAPの方にはvectorのポインタを渡しているつもりなので、[2]のアドレスはvectorのアドレスと一致する。
が期待値なのですが、理由はわかりますでしょうか?
[1]
VECTOR ABC 0x144dd20
VECTOR DEF 0x144dd28
VECTOR GHI 0x144dd30
[2]
MAP itr GHI 0x144dd30 ←vectorの3つ目以降はポインタが一致する
MAP itr ABC 0x144dc20
MAP itr DEF 0x144dcc8
[3]
VECTOR for_each ABC 0x144dd20
VECTOR for_each DEF 0x144dd28
VECTOR for_each GHI 0x144dd30 emplace_back()の時にvectorのサイズが拡張されて中身が再配置されることがある
そうなると拡張前に取ったポインタは無効になる
嫌だったらvectorの挿入削除が一通り終わってからポインタ取るとか、
必要量でreserve()して再配置されないようにするとか、deque使うとかその辺 vector<int> v があるとして、
for(auto i: v)
というループの中で v の要素を変更したときの挙動って言語仕様として決まってるの?
あと、
for(auto i: set<int>(v.begin(), v.end()))
みたいなループを書いたときって set の定義を外に出したときと比べてパフォーマンス上の違いある? >>780
for(auto e: vec){ statement }
はこんな感じで展開される
{
auto && __range = vec;
for (auto __begin = begin(__range), __end = end(__range); __begin != __end; ++__begin) {
auto e = *__begin;
statement
}
}
ポイントとしては内部でイテレータを使ってるからイテレータ無効化ルールに抵触したらおかしな動きになる
(ループの中でvec.push_back()をするとか)。
二つ目の質問については、上の例の
auto && __range = vec;
のように最初に定義域を右辺値参照で取ってるからsetの定義を外に出す必要はない >>778
vector のイテレータが無効になる条件。
https://ja.cppreference.com/w/cpp/container/vector#.E3.82.A4.E3.83.86.E3.83.AC.E3.83.BC.E3.82.BF.E3.81.AE.E7.84.A1.E5.8A.B9.E5.8C.96
emplace_back の場合はそれを実行した後の size() が capacity() より大きいときにイテレータが無効になる。
https://ja.cppreference.com/w/cpp/container/vector/emplace_back
vector は要素が必ず隣接したアドレスに配置されるというルールなので
連続したアドレスで拡張することが出来なければ再配置することがある。
C で言うところの realloc みたいなこと。
要素の数が増えるような操作はだいたいイテレータを無効にすると覚えておけばいい。 >>779,783
vectorは連続したアドレスだから拡張していけば必ず再配置しないといけなくなりますね。
納得しました。
reserveを検討してみます。 inlineについて質問です。
ttps://qiita.com/omuRice/items/9e31d9ba17b32703b3b1
上記を見ると下記のように書いてあります。
//ヘッダファイルでしかinlineで定義できない
//別ファイルで書くとinline展開の時にエラーになる.
しかしヘッダファイルではなく、クラスの本体ファイルの方に書いてもエラーになりませんでした。
c++11を使っているのですが、最新ではエラーになるということでしょうか? よく読めよ
(本来だったら、ヘッダファイルにクラス定義をしてメンバ関数の実装は別ファイルで行なった方が適切です。(Allocationエラーを防げる)) inline関数を定義したファイル内からそのinline関数を呼ぶ分にはエラーにならない
別ファイルでmyClass.hppをインクルードしてinline関数を呼ぼうとするとエラーになる
という意味ではないだろうか >>787
なるほど。
自身のファイルならinlineの関数も見えているから展開できる。
他のファイルで使うときはinline展開する中身が見えないからエラーになる。
というのがしっくりきそうですね。 そのAllocationエラーを防げる、って何の話だろう 上のqiitaは初心者っぽいし正しいことを書いてるとは限らない >>789-790
俺はそれよりも「インラン展開」の方が気になる 今のinlineの意味は「同じ定義である限り何度でも定義していいよ」だからな
展開云々はコンパイラが勝手にやる話であってプログラマが指定する話ではない
上のqiitaの人は昔のネット記事を読みながら勉強したんだろう でもまあ各翻訳単位に定義があれば結果的にインライン化しやすくはあるよな。 今のinlineの効果は元のinlineの効果の必要条件 788です。
私が作成しているプログラムではinlineに変えると逆に遅くなってしまったので元に戻しました。。 >>783
>要素の数が増えるような操作はだいたいイテレータを無効にすると覚えておけばいい。
削除は!?
要素の削除はどうなるのです??!! ……素朴に考えると範囲for文の中で削除してもよしなにやってくれそうな気はする
for(auto blt: enblts){
if( blt.isDead() ) enblts.erase(blt);
}
しかしこれはC++でもJava(remove)でも願い通りには動かない
でも弾幕ゲームをやってる初心者の直感では正しい
としたらこれから先の時代はフィルタで書いた方がいいのかもしれない
erase_if( enblts, [](Bullet blt){return blt.isDead();} );//c++, vector
enblts.remove_if( [](Bullet blt){return blt.isDead();} );//c++, list
enblts.removeIf( blt -> blt.isDead() );//java
enblts = filter( lambda blt: blt.isAlive(), enblts )#python
@enblts = grep{ $_->isAlive() } @enblts;#perl >>798
C++20 で ranges が入るよ。 >>798
listなら直感どおりに動くぞ
やっぱlistなんだよなあ ↓こういう事って可能ですか?
class AClass
{
};
class BClass
{
public:
void Test();
};
int main ()
{
AClass a;
BClass b;
a += { &b, &BClass::Test }; //これを実現したい
} >>802
何をやりたいのかよくわからんがエスパーしてみると、メンバ関数ポインタやstd::function、演算子オーバーロードあたりを使えばいいのか AClass::operator+=(std::initializer_list<void*>)でも実装すればいいのか?試してないけど {}で囲った物を、演算子やら関数なんかの引数として動くようにできるのか。言語仕様的に駄目なのかよくわからん。
ちなみに{}内の要素は異なる型が混在する。
C#のeventみたいな物を非マネージC++環境で作れないかと試している。
で、クラスメンバ関数の扱いで試行錯誤中。その他もろもろの実装はやれてるので、残りはこれだけ。 関数テンプレートのテンプレート実引数推定時、引数に渡した{}は真っ先にinitializer_listとして推論されるので、異なる型を混在できない
引数をテンプレートじゃなくて、集成体とか普通のクラスにしとけば{}で渡せるけど、予め{}の中に入れられる型を固定しなければならない こういうこと?
#include <iostream>
#include <vector>
#include <functional>
class AClass {
public:
void operator+=(std::function<void()> f) { handlers.push_back(f); }
void notify() { for (auto &f : handlers) f(); }
std::vector<std::function<void()>> handlers;
};
class BClass {
public:
void Test(){std::cout << __func__ << std::endl;}
};
int main () {
AClass a;
BClass b;
a += std::bind(&BClass::Test, &b);
a.notify();
} >>809
一番初めに書いたけど、
a += { &b, &BClass::Test };
こういうすっきりした書き方ができないかと考えていたわけで。
std::function系はC#のeventで言う -= の挙動の実装が難なので、使っていません。
できないっぽいのでこの質問は終了とさせていただきます。
ご助言していただいた皆様ありがとうございました。 c#ぽく書くのには限界あるよね
自分の場合は名前付きでstd::functionで持って
a.add("b",[&]{b.Test();})
みたいにしているな。 EnumProcessModules でメインモジュール含め、全モジュールのベースアドレスとイメージサイズをゲットできると思うんですが
この範囲にないメモリ領域かつ、プロセスがコミットしてるメモリ領域って何が載っているんでしょうか?
検索していくと、MEM_COMMIT かつ PAGE_READWRITE かつ MEM_PRIVATE で、
プログラム中に書いた文字列がヒットするような領域もあるんですが >>803
リンクリストは速度的にはオールマイティーに近いデータ構造で、イテレートの速度も配列と同程度。 >>813
リンクリストが劇遅だと思っている人は、マシン語レベルでどういうコードになっているか分かって無いために、効率の良い使い方ができていないため。
正しく使えば、動的配列より平均速度もメモリ効率も速くなる確率が高いデータ構造。 自己レスになりますが下記様なコードで最初の目的が達成できました。可変のコンストラクタ作っとくと{}の初期化の振り分けできるんですね。
template<class FUNC_TYPE>
class MetaFunction;
template<class ...ARG>
class MetaFunction<void(ARG...)>
{
public:
template<class ...INITARG>
MetaFunction(INITARG... arg) { Init(arg...); }
template<class T>
void Init(T* Instance, void(T::*proc)(ARG... arg))
{ //メンバ関数用の初期化
}
};
template<class FUNC_TYPE>
class EventHandler;
template<class ...ARG>
class EventHandler<void(ARG...)>
{
using META_FUNC = MetaFunction<void(ARG...)>;
public:
template<class T>
void Add(T* Instance, void (T::*proc)(ARG... arg))
{ //追加処理とか
}
inline EventHandler& operator+=(const META_FUNC& func)
{
this->Add(func);
return *this;
}
}; >>812
いろいろググってみましたが、分かったような分からんような…
とりあえず、MODULE_INFO.SizeOfImage は、読み込まれた Portable Executable のサイズを表してるっぽい?んでしょうか
コード命令が入ってる .text や、グローバル変数が入ってる .data 領域などいろいろ領域があってフォーマットが決まってるみたいだけど、
実行時のヒープやスタックとかは入ってないっていう認識で良いんでしょうか
PE のフォーマットググっても、exe をバイナリエディタで見たときのフォーマットは結構出てくるんですが、
メモリに載せた時のフォーマットって出てこないんですよね…、EXEをバイナリエディタで見た時と似たような感じだとは思うんですが多分まんまではないですよね >>816
ReactOS のソースコードを見てみれば? 遅いと思うとかじゃなくて実際にやった結果
listは激遅
dequeが1番良い
追加削除してもな >>812
C++関係ないからWin32APIスレとかで聞けばいいんでないの? >>813
リンクリストがオールマイティというのは、お前がリンクリスト使う処理しか書かないからというだけじゃね? >>817
検索してみたけど、大規模なソースコードっぽいので、じっくり調べるには時間かかりそうです
でもありがとう
>>819
なるほど、そっちの方が適切っぽいですね、ありがとう >>782
丁寧に説明していただいてありがとうございます! ウヘン参照はどんなときに役立つんだ?
即値が代入出来るようになっただけか? >>825
右辺値参照は右辺値(何もしないとその場で消えてなくなってしまうもの)をコピーを発生させずに捕まえておくことができる。
例:
>>782の
auto && __range = vec;
(正確にはauto&&はvecが左辺値の場合は通常の参照に、vecが右辺値の場合は右辺値参照になる)
他には関数のオーバーロードと組み合わせて引数が左辺値なのか右辺値なのかを区別して処理を振り分けることができる。
例:
void func(std::vector<int>& vec){ std::cout << "左辺値専用の処理" << std::endl; }
void func(std::vector<int>&& vec){ std::cout << "右辺値専用の処理" << std::endl; }
int main(){
std::vector<int> vec;
func(vec); // -> 左辺値専用の処理
func(std::vector<int>{1,2,3}); // -> 右辺値専用の処理
return 0;
} 右辺値参照はほとんどムーブのための機能と言ってもいいかな。
左辺値か右辺値かを「区別」できることが重要であって、
参照の機能として特別なものがあるわけではない。
この区別が必要になったのはコピーの文脈かムーブの文脈かを知るため。
std::move が右辺値にキャストするだけということからも右辺値とムーブの関連性の強さが感じられる。
その上で右辺値参照と左辺値参照を自動で振り分ける参照 (ユニバーサル参照) を使えば
定義はひとつしか書いていないのに左辺値と右辺値の両方に対応できているなんてことも出来る。
ただし、右辺値参照は左辺値だということを忘れないように。
参照が左辺値参照か右辺値参照であるかを区別して再度振り分けなおすために std::forward がある。 auto&&は右辺値参照のくせに左辺値を束縛できるぞ ユニバーサルはテンプレートの文脈(なおかつTがテンプレート仮引数そのもの)
でなければ使えない
便利さばっか強調してると誤解招くぞ >>828
auto&& はどこでもユニバーサル参照になる。 arithmeticとかpromotedってなんぞ
c++11以降のpow(int, int)の返り値はintなのですか? >>831
候補として書いてある通りの型しかないよ。
https://ja.cppreference.com/w/cpp/numeric/math/pow
だけど、普通にオーバーロードしたら曖昧な状況が出来る場合があるだろ。
float foo(float x) { return x; }
double foo(double x) { return x; }
int main(void) {
foo(1); // どちらを呼び出せばいいのかわかんのでエラー。
return 0;
}
かといって int 版を追加、 long int 版、 long long int 版を追加……とかしていくのは面倒だなぁってことになるわけ。
それも二引数だったら全部の組み合わせが必要になってくる。
で、関数テンプレートで算術型ならなんでも受け取れるようにしておいて候補のどれかに振り分けるようにしようみたいな。
そういう感じ。
うまいこと振り分けなおす関数テンプレートがあるってだけ。 c++のお勧め本教えて
初心者ではないけど、ここの話に付いていけるようにちゃんと学習したく。 とりあえずeffectve modern c++読んで
次は「ISO/IEC 14882:2017 Programming Languages -- C++」とかいう本を読むといいよ >>832-833
ありがとうございます
妄想でした ステマというか、C++ の開発者で、
標準化委員会の江添亮、επιστημη(エピステーメー)、高橋 晶などを、
知らない香具師は、いないだろ C++11/14 コア言語、江添 亮、2015
でも、この本は、プロにとっては、神の書!
規格書の意味を、簡潔なソースコードで例示したのだから
でも、C++の恐ろしいのは、これでもすべてじゃない!
あまりにもルールが多すぎるから、省略ばっかりw 組込み開発者におくるMISRA‐C:2004―C言語利用の高信頼化ガイド、MISRA‐C研究会、2006
この研究会は、トヨタなど大企業から、数十人のベテが集まって、
簡潔なソースコードで例示したけど、
江添の「C++11/14 コア言語」は、一人で書いたのが恐ろしい。
エベレスト単独登頂ぐらいの記録w
あまりにも、crazy >>844
内容に間違いないことどうやって担保してんの? その本に限ったことではなく
聞いた話は他のソースで裏を取るのが
騙されたくない人のすることだ
お昼のワイドショーに洗脳されるBBAがこの逆をいく例 >>846
ニコ生・角川の社員が、テストするのかな? 原稿のコードを自動でチェックするシステムくらいは作れるだろ
他の間違いはしらない >>851
そこを指摘したつもりじゃなかったんだけど、確かにセミコロン抜けてるね。
> C * ptr = &c 言語についてあれこれ言うなら今時は必要な視点だろ。
20年前で時間が止まってんのかね。 コードのチェックについてはその後反省して改善したらしいよ。
https://cpplover.blogspot.com/2016/09/c17.html
> 参考書のソースコードからサンプルコードを抽出してコンパイルするテストは、適当なツールがなかったので適当に実装した。C++で書いて200行ぐらいだった。 ストラウストラップの本こき下ろしてたクセにテメェもろくな本書けないっていう
ストラウストラップの本拾い読みする方が何万倍ありがたいわな 江添さんのC++入門本を読んでいますが、「末尾再帰」を完全に間違えていますね…
私と同じ間違え方でしたが、私以外にも間違える人がまだ居るようですね
view-source:https://ezoeryou.github.io/cpp-intro/#再帰関数
>int factorial( int n )
>{
> if ( n < 1 )
> return 0 ;
> else if ( n == 1 )
> return 1 ;
> else
> return n * factorial(n-1) ;
>}
>この関数は、引数nが1未満であれば引数が間違っているので0を返す。そうでない場合でnが1であれば1を返す。それ以外の場合、n * factorial(n-1)を返す。
>このコードは末尾再帰になっている。 ええ・・・本にする前に誰も気付かんかったんか・・・ >>860
ところでそのケースは末尾再帰ではないが、
gcc で -O2 を付けるとループに最適化するんだ。
賢いなぁ! 大抵一番目の引数はレジスタで代用したりする最適化するよね >>864
それは最適化ではなくABIで決まっていることでは >>860
>return n * factorial(n-1) ;
n を掛けたら、ダメなのか。
return factorial(引数)としないといけないのか
関数の引数に、蓄積器を持つように、変形しないといけないのか スタックが何を保持しとかないといけないか考えたらわかることだけどね。 >>867
末尾で呼び出した関数の返却値を「何も加工せずに」そのまま返却値にするような場合は、
素朴なスタックを使う ABI だと積んだのを直後に降ろす操作になるだけなんだ。
だから相殺してスタック操作を消せる。 call と ret からスタック操作を消すとジャンプになるという理屈。
Wikipedia の説明とかを見てもわかりにくいんだけど、スタックの動きで考えるとわかりやすいと私は思う。 >>869
32BIT の x86のアセンブラで書けば、
push dword ptr a2
push dword ptr a1
call func_addr
add esp,8
ret
となっているのを
mov eax,a1
mov [ebp+xxx1],eax // xxx1は仮引数1のスタック上の相対位置
mov eax,a2
mov [ebp+xxx2],eax // xxx2は仮引数2のスタック上の相対位置
jmp func_addr
などとすると。再帰を行わなくても
return retcode; 文は、
mov eax,retcode
add esp,8
ret
とコンパイルされるから、結局等価になる。 コンパイラに「inline指定された部分がインライン化できなかったら警告」
みたいなオプションがあるけど、それと同様に、
プログラマが末尾再帰のつもりで書いた関数(ソースに明示する)が
実際には末尾再帰じゃない場合に指摘してくれるような機能はないじゃろか。
最適化機構の中でチェックできてるはずだし、学習の役立ちそうな気がする。
末尾再帰に慣れた人には不要な補助輪だろうけど。 二本のスタックを使って木をコピーする方法を思いついてしまったかもしれない。 心底どうでもいい機能を無駄に入れようとするな
そんなことするくらいなら自力で再帰でない書き方する方がまともな対応
スタック消費を気にするなら再帰で書こうとすること自体が間違ってる 江添さんがこのスレを見てれば委員会に提案してくれるかも。 明示的にオーバーライドしないとできない様に制限する機能ってないの?
たまに同名同タイプで気づかずにオーバーライドしてしまった事があるんだが。 規格はコンパイラの警告は決めてない
警告機能が欲しいならコンパイラの開発者に要望を出すんだな >>1
アセンブリファイル出力を行うようにコンパイルオプションを設定して、自分で出力アセンブリコードを見ればいいだけ。 意図したとおりの訳になったかどうかが問題になるのはスポットで全域じゃないからな
ただ、そういう箇所はコンパイラの出力を参考にアセンブラで書くべきだと思うが >>875 gcc の ver.5 だと -Wsuggest-override って警告オプションがあるね。
これと警告をエラー扱いにする指定を組み合わせればいいのかな。 別に
アーキテクチャ依存の話を持ち出さずとも、
fractional(n) = n * fractional(n-1)
とゆー事実をもってただちにfractional(n)は末尾再起と言える
なぜなら
fractional(n) = n * ((n-1) * fractional(n-2))
= n * ((n-1) * ((n-2) * fractional(n-3)))
= ....
となってfractional(0)に至るまで延々展開でき、*が可換である故にこれは
fractional(n) = n * (n-1) * fractional(n-2)
= n * (n-1) * (n-2) * fractional(n-3)
= ....
となって右端を延々展開して「も」得られるからである
*の可換性への依存を良しとしない立場をとったとたん、末尾再起関数と認められるものは
f(n) = f(n-1)
とゆーnに関する恒等写像のみとなる
そう言いたいのであれば別に止めはしないがそっちの方が異端じゃないの;
つまり頭おかしい >>881
>>881
>fractional(n) = n * fractional(n-1)
fractional(n-1) から値が帰ってきたあと、その値と n とを掛け合わせる計算は fractional(n) の関数内で実施しているでしょう?
コールした関数から戻ったときに、そのままなにもせずに得た値をリターンするのならば末尾再帰ですが、
この場合は得た値を加工してからリターンするのだから、これは末尾再帰とはいいません
> fractional(n) = n * (n-1) * fractional(n-2)
> = n * (n-1) * (n-2) * fractional(n-3)
>= ....
>となって右端を延々展開して「も」得られるからである
展開可能であることと末尾再帰であることはなんの関係もありません
>*の可換性への依存を良しとしない立場をとったとたん、末尾再起関数と認められるものは
> f(n) = f(n-1)
>とゆーnに関する恒等写像のみとなる
* の可換性はなんの関係もありません
引数を一つに限定するのならそうですが、プログラム言語は引数を二つ以上持ってもいい
普通は f() の引数を二つ以上とって、その中にアーキュムレータを置いて末尾再帰にします。
f(s, t) = f(u, v) = f(w, x) = …
むしろこっちの方が普通の末尾再帰といっていいでしょう >展開可能であることと末尾再帰であることはなんの関係もありません
>* の可換性はなんの関係もありません
大きく出たな…
まず右端展開の繰り返しにより表現可能でありかつ末尾再起化できない関数というものは無い
なぜなら、右端展開の繰り返しを手続き的に書けばループに他ならんぬ、、、
逆も真で、ループとして書ける関数なら右端展開の繰り返しとしても表せるんであーる
つまり、右端展開の繰り返しにより表現可能であることと、末尾再起化できる関数というものは同値
で、アキュムレータを使った複数引数の関数化というものは、関数の表現を右端展開繰り返し可能な形に直しているにすぎない
で、右端展開の繰り返しにより表現可能かどうかには演算子の結合則が関係する例は
>>881に挙げたとーり
実際、演算子の結合則が成り立たない例として、Aが行列でIが単位行列のとき
fractional3(A) = fractional3(A - I) (A - I) ・・・(1)
というブツを考えると、この関数は右端展開可能でないからもはや末尾再帰化はできない
Aが実数でIが1なら末尾再帰化できるのに…! 末尾再帰であることと末尾再帰に変換できることは区別しようや 末尾再帰に書き換えられることなんか誰も否定してないのに一人で暴れてる 訂正orz、
×: 結合則
○: 交換則
あとなんか式(1)は末尾再帰化可能な気がしてきたorz そりゃ交換則なんか末尾最適化に何の関係もないからな >>883
>まず右端展開の繰り返しにより表現可能でありかつ末尾再起化できない関数というものは無い
>なぜなら、右端展開の繰り返しを手続き的に書けばループに他ならんぬ、、、
理解が粗いと思います
あなたのいう「右端展開」が繰り返し適応可能であればループに展開できる…@
と置いたとき、
@が事実だったとしても、それは末尾再帰となんの関係もありません
末尾再帰の最適化とは関数コール命令+関数リターン命令(call 〜 ret) をジャンプ命令に変換するという最適化でしかなく、
再帰的に記述された関数定義をループに変換する最適化の集合を「末尾再帰という」、わけではないのです
あなたは末尾再帰を広く捉えすぎです >>888
ちょっCPSって継続と書いてある
右端展開の繰り返し表現可能ということと、継続で表せることは自明な勢いで同値なのでは…
つまり漏れの面の皮を通って赤面させるほどの目新しさのインパクトは無いキモス、
>>889
AとBに何の関係も無い、とは、Aの真偽とBの真偽が独立のことを言うはず…
この場合「右端展開の繰り返しで表現可能」と「ループに展開できる」ことが同値なのであるから、
何の関係も無いというのは強弁に過ぎるのでは…
>末尾再帰の最適化とは関数コール命令+関数リターン命令(call 〜 ret) をジャンプ命令に変換するという最適化でしかなく
最適化した結果のみを末尾再帰というのであれば狭く捉え過ぎwwwwww
徹頭徹尾アセンブラで議論してろよ;;
そうではなくて末尾再帰の最適化の話に限定するのであればスレを分けた方が適切なのでは… >>890
>この場合「右端展開の繰り返しで表現可能」と「ループに展開できる」ことが同値なのであるから、
>何の関係も無いというのは強弁に過ぎるのでは…
>>889 はそんなことを言ってはいません
>「右端展開の繰り返しで表現可能」であれば「ループに展開できる」できる…@
とおいたとき、
@と末尾再帰とが、何の関係もない、といっているのです
>最適化した結果のみを末尾再帰というのであれば狭く捉え過ぎwwwwww
>徹頭徹尾アセンブラで議論してろよ;;
最適化を実施するのに、あれこれ解析する必要がなく機械的な命令の置き換え/書き換えだけで可能である、というのが末尾再帰の肝です
まあアセンブラを理解できないようでは C/C++ の理解も薄い弱い、とは思ってはいますが
>そうではなくて末尾再帰の最適化の話に限定するのであればスレを分けた方が適切なのでは…
まず、末尾再帰とはなにか?を両者で合致するように合意をとるのが先決でしょう 厨二プログラマが食いつきやすい三大話題
・再帰
・例外処理
・
おっさんプログラマが食いつきやすい三大話題
・インデントルール
・命名規則
・ >893はID:vZ2zRqlYが指を咥えて見てるだけの話題 厨二プログラマが食いつきやすい三大話題
・再帰
・例外処理
・標準化委員会
おっさんプログラマが食いつきやすい三大話題
・インデントルール
・命名規則
・原点回帰 厨二にもおっさんにもボコボコにされるだけで歯が立たないやつ悔しそう もっと簡単に考えろ
一般に再帰は階層に復帰したときに必ず元の状態に戻さなければならない
復帰後の階層固有の計算に必要だからだ
しかし復帰後に階層固有の計算がない末尾再帰は戻す必要がない
よってループで書けるというだけの話だ
これを順序非可換の問題ととらえることはまあ理にかなっている
以下左が末尾
f(n+1)x=f(n)h(n)g(n)x≠h(n)f(n)g(n)x
f(n+1)x=h(n)f(n)g(n)x=h(n)h(n-1)f(n-1)g(n-1)g(n)x
f(n+1)x=f(n)h(n)g(n)x=f(n-1)h(n-1)g(n-1)h(n)g(n)x
h(n)h(n-1)が可能であるためにはスタックの復帰が必要よって示された あなた達の話は難しくてよくわかりません!
簡潔に説明すると末尾再帰ってなんなんですか?
普通の再帰と違ってスタックオーバーフローが避けられるってこと? >>895
そしてテスト、保守性といったものには誰も興味を持たないのである。おしまい。 >>898から、>>860は末尾再帰であると言える
g(n)x=nx,h(n)x=xと考える >>901 あんたきのうの>881だよね?
たぶん「末尾再帰」の定義が他の人(たとえば Wikipedia の「自身の再帰呼び出しが、
その計算における最後のステップになっているような再帰」)と違いそうだから、まず定義を示してもらいたい。 いや違うよ
級数積が関数という認識があるかないかが彼とは違う 違うのか、悪かった。
で、あんたの「末尾再帰」の定義はどうなってんの? その昔、こんな再帰もやったがw
JSREE EQU *
* DO PREPARE
BSR *+2
* DO SOMETHING
RTS 「自身の再帰呼び出しが、その計算における最後のステップになっているような再帰」
に異論ない。言葉通りだ
ただしそう定義したものは、>>898の性質を持つ >>906
そうなると >860 の "return n * factorial(n-1) ;" における「最後のステップ」は
再帰呼び出しではなく乗算なので、その末尾再帰の定義には合致しないのでは? >>901を適用して
f(n+1)x=f(n)g(n)x
g(n)x=x'
として、
f(n+1)x=f(n)x'
と書けば納得いただけるだろうか >>908 いやサッパリ。
その g やら x やらが >860 の関数とどう関係してるか、示されてないように思うし、
関係が示されたところで "return n * factorial(n-1) ;" の最終ステップが何であるかに
影響するとは思えない。 こう書いた方がよかったかな
f(n+1)x=f(n)g(n)x
f(n)g(n)=h(n)として
h(n+1)x=h(n)x
具体的には
(n+1)f(n+1)x=nf(n)x
例外は最上位の呼び出し元だけがf(n)xになっていることで、
実質h(n)=n * factorial(n-1)という関数の末尾再帰になっている f(n)xはf(n)の結果にxを掛けるんだからf(n)が最終ステップじゃないだろ まずfactorialを末尾再帰に書き換えられるって話なら、そんなの当たり前だし誰も否定してない
それに加えてお前の書き換え方はおかしい
二重に話が噛み合ってなくて訳がわからない
宇宙人か? おそらくわからないという人は、
末尾再帰⇔ループ
の書き換えがどうなっているのかわかっていない
末尾再帰な関数は、関数の戻り値以外のローカル変数はすべて再利用可能であるのでスタックする必要がない
そしてreturnが返しているのは戻り値である
n*はリターン値に含まれている
よってn * factorial(n-1)は一つの関数単位として扱われ得る
実際にそう扱っているかどうかは実装によるだろうが末尾再帰な関数の定義からは漏れていない >>915
仮に「n * factorial(n-1)は一つの関数単位として扱われ得る」を認めたところで
最終ステップはその「関数単位」とやらであって「自身の再帰呼び出し」ではないので、
末尾再帰とは言えないよね。
・・・ >860 を末尾再帰と言えないと死ぬ病気か何かなの? >>916
factorialの呼び元は大本の読み出し元以外はすべてnがかかっていること
実際にループに書き換えられること
よって>>860を否定する必要はないというだけのこと
否定する必要があるならそれでもいいが意味はあるか? >n*はリターン値に含まれている
>よってn * factorial(n-1)は一つの関数単位として扱われ得る
リターン値に含まれていようが関数の呼び出しに含まれていなんだから「一つの関数単位」にはならんわな。 そもそもこの人の数学とやらが意味不明
> (n+1)f(n+1)x=nf(n)x
乗算なのか関数の適用なのかどっちだこれ?
左辺の(n+1)はどっからでてきたんだよ >>917
ループに書き換えられれば末尾再帰と言えるんならやっぱり Wikipedia の定義と違うんじゃん。
「>>860は末尾再帰であると言える」を否定しないと「末尾再帰」の定義(共通認識)が変わってしまうし、
共通認識を壊す行いを認めることになる。それは害悪。やめてほしい。 末尾再帰とかschemeじゃないと意味無い話
末尾再帰だとループに最適化されることが言語で保証されてるって前提なのだから
そこで言う末尾再帰ではn*f(n-1)みたいなのは違う
だから変形して末尾再帰にしろって話になるのだから >>920
それは
return n * factorial(n-1);
と書いてはいけないと強制するということだろうか
だとしたらそれは間違っている
末尾再帰の定義を満たしているにもかかわらず認めないということはそういうことだ 末尾再帰は関数の最後で自身を呼び出してそれをそのままreturnするものだけ
末尾再帰に変形できる関数は末尾再帰に変形できる関数であって、末尾再帰関数ではない >>922
強制とか間違ってるとか認めないとか
お前は誰と戦ってんの?
誰もそんな話してないんだが
読んでで怖いわ >>923
それでいいと思う
だがだとすれば君らは何がわからなかったのかそれがわからない >>915
>n*はリターン値に含まれている
>よってn * factorial(n-1)は一つの関数単位として扱われ得る
return 式
の式に全部書いてしまえるからといっても、その式の中に存在する演算が複数あれば、それぞれの演算に順序があるわけですから
一つに扱うことはできないでしょう、この場合、リターン値を得た後で * n しているのだから、これは一つじゃなく二つ
したがって >>902 の末尾再帰の定義
>「自身の再帰呼び出しが、その計算における最後のステップになっているような再帰」
には合致せず(なぜならば、この場合の最終ステップは * n をすることだから)、>>860 で引用されたプログラムは末尾再帰ではありませんね >>922
>それは
>return n * factorial(n-1);
>と書いてはいけないと強制するということだろうか
いいえ、単に return * factorial(n-1) と書くのならば、末尾再帰ではなくなるというだけのことです。
>末尾再帰の定義を満たしているにもかかわらず認めないということはそういうことだ
もう一度ききましょう、あなたの「末尾再帰」の定義は何ですか? >>927
あなたのいう、「関数」の定義は何ですか
わたしはn * factorial(n-1)は関数だと思います やっぱりこいつ、末尾再帰と末尾呼び出しの区別がついていないとしか思えない >わたしはn * factorial(n-1)は関数だと思います
これがfractional自身とは異なる以上、末尾再帰にはならんわけ。 >>931
では何がわからなくてここまでの長い議論をしていたのですか?
末尾再帰が理解したいというのなら、定義そのままを暗記するだけで済んだはず
一連の私の書き込みは単に理解の方法を提示したに過ぎず、
それを否定するということは定義が理解できていたということでしょう? 中置で書くから分かりづらくなる
ポーランドか逆ポーランドで書けば自明なのに >>928
>あなたのいう、「関数」の定義は何ですか
>わたしはn * factorial(n-1)は関数だと思います
仮に関数の定義をあきらかにしたからといっても、それは末尾再帰の定義とは関係ないでしょうね
繰り返しますが、末尾再帰の定義は >>902
>>「自身の再帰呼び出しが、その計算における最後のステップになっているような再帰」
であり、>>860 で引用されたプログラムの「自身の再帰呼び出し」すなわち「return n * factorial(n-1);」
は、計算における最後のステップになっていない(なぜならば、最後のステップはこの場合 n * であるから)ので、
>>860 で引用されたプログラムは末尾再帰ではありませんね >>932
>>860は末尾再帰にならないということをアンタだけが理解できていないというだけ。 >>934
それを最初から言っていれば、ここまでの無意味な議論はしなくて済んだでしょうね
よって示された 逆になぜ末尾再帰にするかを考えれば、>>934の制限は強すぎる ID:QlEyGkfmは何でもかんでもここのみんなに教えてもらおうとせず
まず落ち着いて自分のペースでしっかり考えてみたらどうかな
みんな呆れてるよ >>938
昔私が末尾再帰を間違えていたとき、当時からこのコテで煽り気味にやっていたにもかかわらず、最上級の親切を示して
「末尾再帰はジャンプ最適化だ!」
と教えてくださった方がおられました、当時のその方ほどの忍耐力を今回発揮できず、申し訳ございません… 皆さんこそ落ち着いてください
nはスタック変数ではなく、ループのインクリメント変数なんですよ 「末尾再帰」という情報処理用語を定義しているJIS規格票もしくは
"tail recursion" という情報処理用語を定義しているISO規格票の
条項を出せるやついるの?
これだけ上から目線でマウント取っといて
あげくオレ用語だったら恥ずかしいぞ 江添が間違えたのが全部悪い
奴が間違えてなければ同じ勘違いをした気違いを呼び寄せることもなかった 江添氏は勘違いと言うより
末尾再帰というもんを単に知らなかったのではと思ってる
末尾再帰の最適化が保証されてる言語使ってる人じゃないだろうから 消費税の計算を例題にあげたけど、計算方法間違ってたみたいなもの
c++的には関係ない分野の知識 蒸し返して悪いんだけど
>>898 の数式解読できる人いる?
この人何を勘違いしてんのか興味でてきたんだが 「添字を持つ添字」みたいなもんを上手に管理する方法ってある?
例えば、
0 <= i < n である全ての i について a[i] を 0 から m の範囲で動かす
みたいなループの構造を想定してる。
当然大きな多重ループになるから小さい n と m についてしか使えないと思うけど、デバッグなどのときにこういうのを簡潔にミスらず書けたらと思っての質問です >>947
> a[i] を 0 から m の範囲で動かす
これの意味がわからない
具体例書いて >>948
for(a=0; a<m; a++)
for(b=0; b<m; b++)
for(c=0; c<m; c++)
...
という形の多重ループのループ変数 a, b, c,... を a[0], a[1], a[2],... にしたいという意味です。
TeX の文法で数式を書けば
\prod_{i=0}^{n} \sum_{a[i]=0}^{m}
という意味です。
・数式との対応が分かりやすい形で書きたい
・簡潔でミスしにくい形で書きたい
といった理由で質問させていただいてます。 >>948-949
すみません。必ずしも和をとりたいだけではないので、式はあくまで例です。
あとレンジが1つずれてるのもすみません。 >という形の多重ループのループ変数 a, b, c,... を a[0], a[1], a[2],... にしたいという意味です。
やればいいだけの話じゃなくて?質問は何だろう。 >>951
n が実行時に決まるような場合どうしたら良いかという意味です >>949
ループのネストが可変なんだよね
templateが許されるなら再帰template
ダメならきれいには書けないと思う >>953-954
ありがとうございます。
再帰templateで調べてみます。
あと書いてて気付いたのですが、n桁のm進数にループ変数 a[0], a[1],... をエンコードするっていうのも一つの方法かなと思いました。 確かにtemplateでなくても再帰で可能か
ただlambdaで渡せないからstd::functionで包む必要あるね >>949
やりたいことは、係数をm^2の2次元配列xとm^3の3次元配列yに入れておいて、2番目のループではx[a][b], 3番目のループではy[a][b][c]を使用するということか?
サイズ可変でも動的に確保すればいいだけ。 >>957-958
m^n 通りの添字 (a[i] for all i) の組み合わせを列挙し、その中でなんらかの処理をしたいという意味です。
説明の仕方が悪くて失礼しました。 全てのa[i]が始点0,終点mならa[i]でなくてもjとかでよくね? std::sortに並列化+ベクトル化指定つけて実行したら、コア数以上に高速化したんだけど、なんで? >>959
あー全部使うのか
function(a[0],a[1],a[2],a[3],....) >>955
こういう解釈でいいのかな
ループがふたつになるかな
a=new int[n];
for(i=0;i<m^n;i++){
for(j=0;j<n;j++){
a[j]=i%m;
i/=m;
}
function(a,n);
}
delete[] a; >>964
はい。
再帰が難しかったらそれにします。 多重継承のときのCRTPについて説明してるサイトないですか そんなモンがあるなんて初めて知った
やはりC++は奥が深いな >>949
>TeX の文法で数式を書けば
>\prod_{i=0}^{n} \sum_{a[i]=0}^{m}
>という意味です。
絶対ではないが、標準的な数学の記法だと、その意味では、
\sum_{a[0]=0}^{m}・・・\sum_{a[n]=0}^{m}
と書くのがが普通だと思う。
ところでそれは量子力学の経路積分か何かですか?
経路積分の場合は、本によって上記の部分に割と独特の変な記号を使う場合があって、
あなたの書いたように書いてある本もあるかもしれません。
ただ、普通の数学記法だと余り使いませんよね、その書き方は。 >>969
補足すれば、普通の数学記法だと
\sum_{a[0]=0}^{m}・・・\sum_{a[n]=0}^{m} f(a[0],・・・,a[n]) //(1)
ですね。
\prod_{i=0}^{n} \sum_{a[i]=0}^{m} //(2)
の記号の場合は、
X= \prod_{i=0}^{n} \sum_{a[i]=0}^{m} g_i(a[i]) //(3)
の場合は、
b[i] = \sum_{a[i]=0}^{m} g_i(a[i]) //(4)
(i=0, ・・・, n)
を先に計算しておいて、
X = \prod_{i=0}^{n} b[i] //(5)
= b[0]・・・b[i] //(6)
の意味に解釈するのが標準的な数学の記号の使い方だと個人的には思います。
(1)と(3)ではかなり意味が違いますが、(2)の記号を、(1)の先頭に使えるかと言えば、
絶対使えないわけでは有りませんが、使う前に何らかの補足説明が必要になりそうです。 >>970
誤: = b[0]・・・b[i] //(6)
正: = b[0]・・・b[n] //(6) >>967
派生が継承してる複数の基底を受け取りたいとか? int *pInts = new int[10]();
とした場合の最後の()の意味は何でしょうか?
付けない場合との差を教えてください。 >>973
イニシャライザ。
普通のクラスではそれがないときはデフォルトコンストラクタで初期化される (空の括弧があっても無くても同じ挙動) けど、
int 等では初期化を明示しない限り初期化されない。
逆に言えばこの場合は初期化を明示しているので初期化される。 (0 が入る) >>974
有難うございます。では、
int *pInts = new int[3](1,2,3); //(1)
int *pInts = new int[3]{1,2,3}; //(2)
の違いは何でしょうか? >>975
(2) の場合には集成体初期化になる。
https://ja.cppreference.com/w/cpp/language/new#.E6.A7.8B.E7.AF.89
(1) も C++20 からは集成体初期化になる。
だけど gcc と clang の最新版で試しても出来ないっぽいし、
あえて丸括弧で書きたい理由はないなぁ。 >>976
ちょっとまってください。
>>973 の場合の >>976
ちょっとまってください。
>>973 の場合の >>976
ちょっと待ってください。
>>973 の場合の () は、「集成体初期化」のうちの「中身が全く入ってない括弧」と解釈してよろしいのでしょうか? >>979
いいえ。
> initializer が空の括弧の場合、それぞれの要素は値初期化されます。
に該当する。 >>980
最初は集成体初期化を使って、
int *pInts = new int[100](1,2,3); //(1)
int *pInts = new int[100](1,2); //(2)
int *pInts = new int[100](1); //(3)
int *pInts = new int[100](); //(4)
とどんどん()の中の項目を減らして行き、最後に0個にした場合、
推論的な延長線上にあると思えるか、それとも全く違った結果になるかどちらですか? >>981
C++20 的に言えば集成体初期化の文法に統合されたということにはなるんだと思うけど、経緯はよくしらない。 もし、
{1,2,3,0,0,0,0,0}
{1,2,0,0,0,0,0,0}
{1,0,0,0,0,0,0,0}
{0,0,0,0,0,0,0,0}
のようになるんであれば、()は(xxx)のxxxを書かない場合と捉えるのは数学的推論として
正しい見方になりますね。
実際に上のようになるのか、未初期化の部分が残るのかは知りませんが。 >>983
足りない分はゼロ初期化されるよ。
C の時代からの配列の初期化の文法と一貫させてるつもりなんだと思う。 >>983
空の丸括弧でゼロ初期化されるのは C++03 にはすでに有って、
波括弧で初期化する文法は C++11 から入って、
(そこから色々と条件の緩和やら変更やらがありつつ)
空ではない丸括弧で集成体初期化になるのは C++20 からという段階的な変化がある。
追加された文法が既存の文法となるべく一貫性を持つように統合しようとはしているけど、
互換性を壊さないようにというのも C++ の強い要件なので、
正確なルールはごちゃごちゃした条件の塊になりがち。
まあまあ整理されている部分もあるけど、
勝手な予想ではなくちゃんと資料にはあたった方がいいよ。 結局、波括弧と丸括弧はどっちが良いの?
C++11の時点では、波括弧が使えるところでは波括弧使っとけってのがMayers神の教えだったけども 好きなようにやったところで法(規格なりデファクトスタンダード)にはならんだろw よし、じゃあ今から俺が法な。
ここの住人は全員システムハンガリアン強制 >>987
シンタクス的にどちらでも良いときには波括弧を優先した方がよいと思う。
波括弧は縮小変換を許さないので意図しない情報の欠落は防止できる可能性が高い。
縮小変換が必要な場面に限って丸括弧を使えばそこが要注意ポイントってのがわかりやすい。
----
ところで縮小変換より狭化変換という用語の方が好きなんだけど、
みんなどっち使ってる? やっぱ縮小変換の方が標準的かな? >>969-971
> 絶対ではない
> 思う
> 個人的には
話にならん へぇこんな配列の初期化の仕方あるんだねぇ
お前らC++に詳しいじゃん C言語の時点で int a[100] = {0}; でゼロクリア
もはや裏ワザの部類
https://cpplover.blogspot.com/2010/09/blog-post_20.html
int a[2][2] = { 1, 2, 3, 4 } ;
多次元配列の初期化での謎機能
これも裏ワザにしか見えない
裏ワザ・例外・隠し機能が相まって配列の初期化だけで一冊の同人誌が出来上がる >>993
数学の記号法と言うのは本によって違ってるから。
特に物理学は必要に迫られて新しい記法を発明してしまう。 >>998-999
いや、だからなんだよ
なんの主張にもなってないお気持ち表明するだけの雑魚多いな このスレッドは1000を超えました。
新しいスレッドを立ててください。
life time: 35日 16時間 48分 52秒 5ちゃんねるの運営はプレミアム会員の皆さまに支えられています。
運営にご協力お願いいたします。
───────────────────
《プレミアム会員の主な特典》
★ 5ちゃんねる専用ブラウザからの広告除去
★ 5ちゃんねるの過去ログを取得
★ 書き込み規制の緩和
───────────────────
会員登録には個人情報は一切必要ありません。
月300円から匿名でご購入いただけます。
▼ プレミアム会員登録はこちら ▼
https://premium.5ch.net/
▼ 浪人ログインはこちら ▼
https://login.5ch.net/login.php レス数が1000を超えています。これ以上書き込みはできません。