C++相談室 part153
レス数が950を超えています。1000を超えると書き込みができなくなります。
1秒間に1万回くらい数値判定の計算をしてるのですが
Xが3桁の時のみTrueを返すようなコードで一番速いのってどんなコードですかね?
愚直にif(1000>X>=100)でやるのと
if(10>X/100>=1)ではどっちが速いんでしょうか 多くのコンパイラは以下に変形しそうな気がする
if (X-100u<900u)
後者をコンパイラが最適化するかどうかはコンパイラ次第 PCなら1秒に1万回程度なら気にしなくて良い
8bitマイコンだとこの判定だけでも10個以上の命令になったり 長さ数十億のbool型配列用意すれば早いんじゃね
isDigit3[x] だけで出るじゃん 根本的には、速度って環境依存の性質だから、本当に重要な話なら実測で確かめるしかない。
一般論としては、現代のコンパイラはそこらの人間より賢いから、やりたいことを素直に書いて最適化を任せるのがいい。
わかってない人が余計なことをやると、かえって遅くなる可能性が高い。
計算量のオーダーを変えるような、アルゴリズムレベルの最適化なら意味があるんだけど。
小手先のテクニックは通用しないと思っていい。 >>850
いうてほんとに定数式になってくれないと困る場面で定数評価してくれない事態に出くわしてないんだよなぁ・・
constexprなクラスとか作ってればあるのかもしれんが 最適化にも限界はあるから、どういうコードの書き方ならコンパイラが最適化しやすいか、
ってのを知るのは必要なんやろうね
データアクセスの局所化とか偽の依存関係の除去とか typedefで二重定義になった場合さぁ…同じ型だとコンパイルエラーにはならないんだよ…
なんか気持ち悪いので…typedefだけのヘッダーを呼ぶようにしたけど…同じ型だとOKなん? ヘッダーに渡しても同じことか…相互参照してるんだった… Ruby VM では、1秒間に、100万回ループすると、
Ruby中間言語を、JIT で機械語にコンパイルして、
1秒間に、1,000万回ループ出来るようになる いや指定した数だけループしろよ
何勝手に回数10倍に増やしとんじゃい サムソンを守るためのHuawei潰しという側面もある。 文大統領がトランプ大統領に、Huaweiを潰すよう勧めたそうです。 >>863
C++ならはじめから秒2000万回ループできるコードになる このプログラムは応答していないためシステムによって閉じられますって出るんじゃないの。 >>854
手元の32bitマイコン(除算器なし)だと
uint16_t v; に値入ってたとして、
if(v >= 100 && v < 1000) よりは ((v >= 100) & (v < 100p >>871
途中で送ってもうたorz
((v >= 100) && (v < 1000))のが気休め速い感じだったな。
あとLUTもほぼ変わらん。LUTはもう少し複雑な計算で、
かつキャッシュにテーブルが入ってくると鬼速だろうけど。
単純な比較のみだからあまり速い方法ないのかもね〜
ダメ元で掛け算とビットシフトで/100する処理も試したけど
ちょっと遅くなったorz
つか、32bitマイコンだと100us周期程度の割り込みハンドラで
この水準まで自分は気にしないだす。
あとC++ならinline化とかその辺をまずチェックでしょうさ。 >>872
if ((unsigned)v - 100u < 900u)
のが早くない?
テーブルは論外だ
アドレス計算コストの方が高そうだし
ROMサイズやキャッシュ汚染などの悪影響がある if ((unsigned)v - 100u < 900u)
こういうのは減算とコンペア(実質減算)の2回の演算が常に走るから必ずしも速くないんじゃないかな。
&&で繋ぐ方がショートサーキットが働いて1回で済む場合がある。
演算で0との比較に落とせるなら別だけど。 そのくらいなら最適化に任せた方がいい気がするが…… 比較がボトルネックってのは本当だろうかとは思わなくもない
まあ、データ転送とか切り詰めまくって残すは比較のみ、ってのもありうるけど 整数の減算は非常に高速
条件分岐は遅いし分岐予測を汚染する
コンパイラの最適化を見てると良い
範囲判定は大抵>>873のようなコードになる コード的には普通に
if (100 <= x && x < 1000)
と書いておけば良い
コンパイラが最適化するから
x/100を比較するのは
意味的にも意味不明だし
速くなることもない ISRの最適化なら
レジスタを節約して待避する数を減らすとか
レジスタバンクを使ってレジスタを切り替えるとか
RAM上で実行するとか
割り込みを許可せずに高速化とか(MIPSの場合)
まあ色々とチューニング出来る余地がある
小規模DSPなんかだと
いまだにISRをアセンブラで書いたりする バンク切り替えテクニックですか。
むかしのインターフェース誌っぽいですね。 template<size_t A, size_t B>
class tmp{};
template<size_t N>
void test(tmp<N, N>&){
std::cout << “A”;
}
template<size_t A, size_t B>
void test(tmp<A, B>&){
std::cout << “B”;
}
上のような関数があったときにtest(tmp<1,1>{});がどちらを呼ぶか規格で決まってる? using FunctorType = std::function<void()>;
struct RecursiveMapperType;
using InternalMapperType = std::map<std::string, RecursiveMapperType>;
struct RecursiveMapperType : public InternalMapperType
{
RecursiveMapperType(){}
};
こういうコードをネットで見かけたんだけど
RecursiveMapperTypeを前方宣言してInternalMapperTypeを宣言
RecursiveMapperTypeをInternalMapperTypeを継承して作成していることのメリットがよくわからない。
struct RecursiveMapperType : public InternalMapperType
{
RecursiveMapperType(){}
};
using RecursiveMap = std::map<std::string, RecursiveMapperType>
だとだめなのだろうか?
誰か教えて下しあ >>884
上のコードと下のコードの RecursiveMapperType の定義はまったく同じに見えるんだけど、何が違うの? >>885 さん
すみません。
下の方のRecursiveMapperTypeですが継承元消し忘れてました。
下のようなkたちです
struct RecursiveMapperType
{
RecursiveMapperType(){}
};
using RecursiveMap = std::map<std::string, RecursiveMapperType> >>886
それじゃ全然機能が違うっていうかその RecursiveMap 何の役にも立たないでしょ。
元の RecursiveMapperType の機能が理解できてないだけか。 再帰的な構造を定義したくて自分自身の型を含めたものを継承してるわけで
それを実現するには前方宣言するしかない
というね 再帰的なコンテナは、フィールドが出来た時点で破綻するのでは? C++23に持ち越された契約は何が変わるんだろね。 ありがとうございます。なんとなくイメージできました。
コードの設計ってまだよくわからないのですが、
再帰処理のためにこうするのって比較的普通なことなんですか? >>893
知らんよ。
普通かどうかなんて気にしてどうするの?ここで名無しの誰かに yes/no 答えてもらって何か意味ある? >>893
STLのクラスを継承して階層構造を実現するテクは応用編って感じがする
もっと基本的なやり方をするならデザパタのcompositeパターンを使う
とかかね 設計を学ぶならデザパタはひと通り見ておいて損はないぞ newのコストは気にされますが、deleteのコストは見逃されがちです。 あるクラスのコンストラクタのデフォルト引数を変更するときってどうしたらいいの?
オーバーロードすれば良い? stlコンテナを継承するのはアウトだろ。
うまくやらないとデストラクタが呼ばれなくなっちゃうぞ そもそもC++ではデストラクタを仮想にしてないってことは「継承すんなよ」って宣言だからなぁ なんで継承しないようにしたか意見表明文みたいなモンはどっかにあるのか? 仮想関数化するとしない場合に比べて余分なコストがかかるから、必要な理由がない限り基本的にそれは避けるということじゃないかな C++は1クロックでも速く動作させるために非仮想関数をデフォルトにしたのは理解できる
Javaは動作速度よりもオブジェクト指向の継承動作の一貫性を重視してすべて仮想関数にした、これも時代を考えれば理解できる
C#もJavaと同じくデフォルトを仮想関数にしておいて欲しかったのだが、C#はC++を尊重してデフォルト非仮想関数なんだよね
これはちょっと残念 継承して機能追加っていうのがオブジェクト指向的にもどうかと思うね finalキーワードがこの時代にあれば間違いなく付けただろうな
文句言ってる奴はガイジ >>903
継承すんな、は言いすぎ。
private継承なら問題ないと思うけど。実際たまに使われているし。 デストラクタが仮想ではないものを継承したときの具体的な問題は
スライシングが起こりうるということと、
起こってもコンパイラが (少なくともコンパイル時には) 捕捉できないことが多いということにあって、
スライシングが起こらないように使う分には問題はない。
設計的に綺麗かどうかはまた別の話だけど。
shared_ptr が (デストラクタが仮想でなくても) 元の型のデストラクタを呼んでくれたりするんで、
場合によってはそういう設計もアリということなんだと思う。 >>910
デストラクタが仮想なものを継承してもスライシングは起こりうるよね?そこは関係なくね?
https://en.wikipedia.org/wiki/Object_slicing
> In C++ programming, object slicing occurs when an object of a subclass type
> is copied to an object of superclass type: the superclass copy will not have
> any of the member variables defined in the subclass. ... C++自由すぎてしんどいな
後方互換性と引き換えに払った代償か >>911
スライシング自体は起こるけど、それで予想外のことやメモリ管理の矛盾は起こり難い。 自由すぎて困る部分はLinterを併用することで勝手に回避しろってことかな だってCの設計思想が「人間を信用する」だもん
セキュリティが重視される現代的な言語のベースとしては致命的に合ってないんだよね >>913
やっぱり関係がわからない。
デストラクタが仮想ではないものを継承したときに限ってスライシングが予想外のことや
メモリ管理の矛盾につがなる例をひとつでいいから見えてもらえない? A <|- B, C みたいなときにB, CをnewしてA*として管理しようとすると破棄の時にAのデストラクタしか呼ばれない >>911
仮想でないデストラクタが話題のスコープなのに、スライシングにスコープを移したら議論にならないでしょ。
911) デストラクタが仮想なものを継承する→スライシングになるものが存在する
という命題は
910) デストラクタが仮想ではないものを継承する→スライシングになるものが存在する
という命題と矛盾するわけではない(両立する)ので、その議論はあんまり意味がない。 >>910
> スライシングが起こらないように使う分には問題はない。
ここもおかしいんだよね。
デストラクタが仮想ではないものを継承して派生クラスのオブジェクトを new で作って
基底クラスのポインタを通して delete したら未定義動作になるわけだけど、
これはスライシングを起こしていなくても問題になる。
「派生クラスのオブジェクトを new で作って基底クラスのポインタを通して delete」のことを
「スライシング」と呼んでる気配もあるんだけど、それは明らかに誤りだろうし。 >>900
変更ってどうやるの?
毎回好きな引数を与えよってこと?
面倒なので、自分の好きな引数を自分のコードの中ではデフォルトにできれば良いのにと思ったのだが、こういう考えは間違っていますか デストラクタはpublic仮想かprotected非仮想かpublic非仮想finalのどれかにしろ
っていう一般的結論でよくね >>925
自分で書くときはそう
標準のコンテナのように既存のクラスがそうでなかったら?が発端だからなぁ
個人的には仮想デストラクタがなければ継承はしない
(一部のイディオムを除けば)private継承にするくらいなら委譲する。 デストラクタがprotected:であっても非仮想なら継承したらアウトなんじゃ…
派生クラスの破棄時に基底クラスのデストラクタが呼ばれない
的な意味で >>924
オブジェクトを作るための関数を作ってはどうかという意味ですか?
確かにそれで良いのでそうします 【CSS規格、読書感想文】
CSSがアイデアであった段階からスクリプト言語で実装され、初の大規模採用であったネットスケープにおいてもJavascriptによって実装されていたため、規格そのものがC/C++で効率的になるよう設計されていない。※
現行の規格に対して効率的な実装を施したとしても、将来の規格バージョンで維持できると限らないため、結局、スクリプト言語と同様の非効率を許容することになる。
これはつまり、ほとんどのシンボルを動的に確保することを意味する。
※HTML5規格は、C/C++で効率的に実装できるように仕組まれている。 なるほどねー
そもそもCSSのCって要る?
もはやスタイルシートってサイト作成者が決めるものになっているよね
ユーザースタイルシートをカスケード適用できる機能もなくせばさらに効率よくできそう >>927
なんで?~Derived()が~Base()を呼ばない場合なんて存在しないぞvirtualの有無関係なく >>927
型消去とsmart ptr実装で調べるよろし。 定期的に話題になるけど、基底のデストラクタにvirtualが必要なのは
基底型のポインタでdeleteするときだけな
末端のデストラクタさえ呼べれば、次に呼ぶ基底の型は分かりきってるからね
別の言い方をすれば、常に末端の型のポインタをdeleteする分には、virtualなデストラクタなんか要らんということ ポリリズムから出汁をとったみたいないい方しますね。 まあ普通は末端の型を意識しなくて済むからこそ派生の旨味がある訳で >>936
その点については誰もが一度は通る勘違いだよなw
最初はわけも分からず機械的にvirtualつけて回ってたわ うっせえ知っとったわ素でまちがえただけじゃわ!ヽ(`Д´)ノウワーン struct A { virtual void Delete() { delete this; } };
struct B : A { void Delete() { delete this; } };
こうなってりゃ別にいらんな >>795 の同期とか奇妙な質問に思うけど、Javaからくるとそうなるんだな。 javaにだって非同期でメモリ確保するコンテナなんてないでしょ >>942
おとなしく virtual ~A() とするのにくらべて何のメリットも無いな。 「a=1 かつ b=1 以外なら実行」って条件式はどう書くの? >>950
> 「a=1 かつ b=1 以外なら実行」って条件式はどう書くの?
「「a=1 かつ b=1」以外なら実行」なら、
if (!(a == 1 && b == 1)) { 実行(); }
「a=1 かつ「b=1以外」なら実行」なら、
if (a == 1 && b != 1) { 実行(); } >>949
THX
「a=1 かつ b=1」以外なら実行、でした。
私が950でレスするのもお見通しですか?w レス数が950を超えています。1000を超えると書き込みができなくなります。