X



C++相談室 part153

■ このスレッドは過去ログ倉庫に格納されています
0799デフォルトの名無しさん
垢版 |
2020/12/19(土) 22:59:41.56ID:vl/1bKki
確かにCだと必要メモリの問い合わせの為に二度呼び出したり面倒でしたわ…
0801デフォルトの名無しさん
垢版 |
2020/12/19(土) 23:20:05.98ID:biviwPkb
>std::vectorは末尾に0を追加したりしません。
左様いまだにstd::string::c_str()が内部で何をやっているのかわからん…
0804デフォルトの名無しさん
垢版 |
2020/12/20(日) 09:47:23.01ID:C7ljP8CG
>>799
でも「直接メモリいじってる」て感覚があって好みだったなぁ
まあ自己満足でしかないのだけれど
0805デフォルトの名無しさん
垢版 |
2020/12/20(日) 10:51:49.27ID:KSHt8d36
今どきのC++(C++11以降)だと基本的にスコープ抜けたら開放される方式で実装するものなの?
なるべくnewせずにスタック変数にする or ヒープ確保するにしてもスマートポインタ使う
とかで
0808デフォルトの名無しさん
垢版 |
2020/12/20(日) 11:27:39.08ID:KSHt8d36
そうかな?
ライブラリとかでわざわざInitialize/Finalizeとか明示的に呼ばなきゃいけないの
結構ある気がするけど
0809デフォルトの名無しさん
垢版 |
2020/12/20(日) 11:52:43.58ID:mkiVvOjR
Finalizeが失敗する可能性があってエラーハンドリングしないといけない場合はあえてそうしているかもね
0810デフォルトの名無しさん
垢版 |
2020/12/20(日) 13:25:24.04ID:8M1CEzDz
あえてね!
0811デフォルトの名無しさん
垢版 |
2020/12/20(日) 13:31:53.40ID:1w6q/2mK
というかスコープ内で完結しない、グローバルな状態を持つものならそうするやろ
0813デフォルトの名無しさん
垢版 |
2020/12/20(日) 13:52:50.85ID:BqPIIXKk
お前が挙げてたそういうライブラリがInitialize/Finalizeの中で何やってるか考えれば自ずと答えはでるだろ
0814デフォルトの名無しさん
垢版 |
2020/12/20(日) 14:05:47.98ID:S1Ae4PMu
グローバルな初期化と後始末ならInitialize/Finalizeとか明示的に呼ぶ設計のが一番闇が少ない
ファクトリメソッドでオブジェクトを作ることにして、ファクトリ元オブジェクトの
コンストラクタとデストラクタでそれぞれInitializeとFinalizeでも良いが(呼び忘れ対策は完璧になるが
InitializeやFinalize自体のエラーハンドリングを考えるとやっぱビミョー
0815デフォルトの名無しさん
垢版 |
2020/12/20(日) 21:00:32.48ID:POdM0+je
変数名で対象変数のポインタを取得してくる実装(リフレクション?)をしたいんですけど
対象変数をポインタテーブルとかに書き下すことなくコンパイル時に変数名リテラルと対応するポインタを自動生成することってできますか?
0821デフォルトの名無しさん
垢版 |
2020/12/21(月) 02:47:40.73ID:HVkDagg+
数値計算に興味がある方に聞きたいのですが、ベクトル演算はどのように実行していますか?
valarrayかeigenなのか、vectorでforを回すのか…C++の常識ではどうやるのか伺いたいです
0822デフォルトの名無しさん
垢版 |
2020/12/21(月) 03:43:19.44ID:tQs5NvLs
>>821
blasやlapackにルーチンがあるならそれを使う(ラッパーを作る)
要素の持ち方はvectorでもvalarrayでもその他クラスでも、一次元的にメモリに格納されるなら何でも良い
二次元以上の配列が行優先か列優先かさえ固定しておけば何でも良い
0826デフォルトの名無しさん
垢版 |
2020/12/21(月) 19:14:50.06ID:5SN4/ItM
みなさんありがとうございます
主に多次元の常微分方程式を解く目的でFortranからc++へ移行しようと考えていたのですが、ベクトル和やスカラーベクトル積等の計算がFortranほど簡単ではなさそうに感じて質問しました
eigen等を活用しつつ頑張ってみます
0827デフォルトの名無しさん
垢版 |
2020/12/21(月) 20:22:43.20ID:94n2fENi
そりゃそうだろな
汎用機の時点で科学計算と銀行計算の両方ができる
だから科学専用に作られているFortranと汎用のC言語は根本的に用途が違う

そもそもFortranの後に作られたのがC言語だし、時期も近いし、
だからFortranで出来ることをわざわざC言語でやったりはしない、
用途での住み分けがそのころからある

後発の方が簡単に出来るというのは幻想
0828デフォルトの名無しさん
垢版 |
2020/12/21(月) 21:07:13.89ID:HyYYfsZ0
簡単なことは簡単に言え

既成のソフトを使い慣れているならそれを使え
不満があるときに自分の理想との違いを埋めるのに
打って出る手段の1つにプログラミングがある
それはC++に限らない
たまたまC++を選んだのなら自らの名誉に恥じぬ努力をせいや
これまたC++に限ったことではないがな

あれ使えばいいやー、これ使えばいいやー
自分なんか物事を考えるだけ無駄なんだー

こういうスタンスのやつ、俺は反吐が出るほど大大大大大嫌い
0829デフォルトの名無しさん
垢版 |
2020/12/21(月) 23:35:19.34ID:5SN4/ItM
ヘッダファイルに
double hoge = 1.0/3.0;
みたいに書いてた場合、除算はどのタイミングで行われるんですか?初回呼び出し時のみですよね?
0830デフォルトの名無しさん
垢版 |
2020/12/21(月) 23:51:47.03ID:3sOyVj6l
大昔(40年ぐらい前?)とかもんのすごい特殊な環境用のコンパイラはしらんが
今の普通のコンパイラではそれはコンパイル時に計算される
0833デフォルトの名無しさん
垢版 |
2020/12/22(火) 02:07:17.74ID:bzbnZ90n
>>826
Fortranでも基本的にblasとかlapackに投げるだけじゃないの?
しかもC/C++からFortranルーチン呼べるし

「FortranではやりやすかったがC/C++ではやりにくかったこと」って非常に興味あるから具体的にどういうものか教えてほしい
0834デフォルトの名無しさん
垢版 |
2020/12/22(火) 06:36:52.20ID:GAvzsgv/
blasとかlapackがfortanで記述されてるからね
中身いじるような人がどれほどいるかはわからんけど
0839デフォルトの名無しさん
垢版 |
2020/12/22(火) 10:18:51.71ID:hq0fof4K
Cコンパイラ作ったよね。
0841デフォルトの名無しさん
垢版 |
2020/12/22(火) 16:28:31.76ID:cQdMNR1v
>>834
中身いじるような人がいないからこそ、fortranで(blasやlapack)でできる線形代数計算はC/C++でもできるだろうと思うのだが
0842デフォルトの名無しさん
垢版 |
2020/12/22(火) 23:28:55.02ID:cWduRySe
constexprともなるとどこまでコンパイル時計算してくれるかは
処理系依存と聞く…!
関数が絡んだ場合だけかもしれんが
0843デフォルトの名無しさん
垢版 |
2020/12/22(火) 23:41:36.57ID:Yt10VcGs
>>842
constexpr にまつわるルールはコンパイル時計算してくれる最低ラインを定めるもの。
どこまでコンパイル時計算してくれるかが処理系依存なのは初期のC言語から変わりないよ。
0846はちみつ餃子 ◆8X2XSCHEME
垢版 |
2020/12/23(水) 02:19:42.25ID:wEQUKH0P
>>844
constexpr 指定が付いた関数は定数式が要求される文脈において
与えられる引数も定数 (定数式) である場合に限りその関数呼出しは
定数式という扱いになる。

定数式が要求される文脈で入力が定数でないならエラーになるし、
定数式が要求されていない文脈であれば実行時計算だよ。

実行時計算にはならない (実行時計算が必要な文脈だとエラーにする) 指定として consteval が導入されたのは、
constexpr の文脈依存な挙動が面倒だと思ったやつがいたからだと思うよ。
0850はちみつ餃子 ◆8X2XSCHEME
垢版 |
2020/12/23(水) 09:20:18.63ID:wEQUKH0P
自動で呼び分けて欲しいと思うこともあれば
コンパイル時に限って欲しいことだってあるだろう。
0851デフォルトの名無しさん
垢版 |
2020/12/23(水) 19:37:56.48ID:lj5PdyQr
1秒間に1万回くらい数値判定の計算をしてるのですが
Xが3桁の時のみTrueを返すようなコードで一番速いのってどんなコードですかね?
愚直にif(1000>X>=100)でやるのと
if(10>X/100>=1)ではどっちが速いんでしょうか
0853デフォルトの名無しさん
垢版 |
2020/12/23(水) 19:43:53.01ID:PgZc4XsV
多くのコンパイラは以下に変形しそうな気がする
if (X-100u<900u)

後者をコンパイラが最適化するかどうかはコンパイラ次第
0854デフォルトの名無しさん
垢版 |
2020/12/23(水) 19:47:49.74ID:PgZc4XsV
PCなら1秒に1万回程度なら気にしなくて良い
8bitマイコンだとこの判定だけでも10個以上の命令になったり
0855デフォルトの名無しさん
垢版 |
2020/12/23(水) 20:03:20.62ID:rWjdGSAm
長さ数十億のbool型配列用意すれば早いんじゃね
isDigit3[x] だけで出るじゃん
0857デフォルトの名無しさん
垢版 |
2020/12/23(水) 21:04:06.12ID:oO0RWe4j
根本的には、速度って環境依存の性質だから、本当に重要な話なら実測で確かめるしかない。

一般論としては、現代のコンパイラはそこらの人間より賢いから、やりたいことを素直に書いて最適化を任せるのがいい。
わかってない人が余計なことをやると、かえって遅くなる可能性が高い。

計算量のオーダーを変えるような、アルゴリズムレベルの最適化なら意味があるんだけど。
小手先のテクニックは通用しないと思っていい。
0858デフォルトの名無しさん
垢版 |
2020/12/23(水) 22:00:42.78ID:p3n5tJou
>>850
いうてほんとに定数式になってくれないと困る場面で定数評価してくれない事態に出くわしてないんだよなぁ・・
constexprなクラスとか作ってればあるのかもしれんが
0859デフォルトの名無しさん
垢版 |
2020/12/23(水) 22:21:55.80ID:JqE6cd4a
最適化にも限界はあるから、どういうコードの書き方ならコンパイラが最適化しやすいか、
ってのを知るのは必要なんやろうね
データアクセスの局所化とか偽の依存関係の除去とか
0860デフォルトの名無しさん
垢版 |
2020/12/23(水) 23:11:04.90ID:pgaSoeQc
typedefで二重定義になった場合さぁ…同じ型だとコンパイルエラーにはならないんだよ…
なんか気持ち悪いので…typedefだけのヘッダーを呼ぶようにしたけど…同じ型だとOKなん?
0861デフォルトの名無しさん
垢版 |
2020/12/23(水) 23:12:13.58ID:pgaSoeQc
ヘッダーに渡しても同じことか…相互参照してるんだった…
0862デフォルトの名無しさん
垢版 |
2020/12/23(水) 23:13:21.42ID:pgaSoeQc
一応…間違えないように…ヘッダーに集約しておく…
0863デフォルトの名無しさん
垢版 |
2020/12/23(水) 23:13:34.29ID:KqYWGLnc
Ruby VM では、1秒間に、100万回ループすると、
Ruby中間言語を、JIT で機械語にコンパイルして、

1秒間に、1,000万回ループ出来るようになる
0865デフォルトの名無しさん
垢版 |
2020/12/24(木) 06:19:28.22ID:TzdYJrci
サムソンを守るためのHuawei潰しという側面もある。
0867デフォルトの名無しさん
垢版 |
2020/12/24(木) 06:58:51.74ID:TzdYJrci
文大統領がトランプ大統領に、Huaweiを潰すよう勧めたそうです。
0869デフォルトの名無しさん
垢版 |
2020/12/24(木) 08:12:44.86ID:TzdYJrci
このプログラムは応答していないためシステムによって閉じられますって出るんじゃないの。
0871デフォルトの名無しさん
垢版 |
2020/12/24(木) 11:16:41.02ID:h4Gph9I0
>>854
手元の32bitマイコン(除算器なし)だと
uint16_t v; に値入ってたとして、
if(v >= 100 && v < 1000) よりは ((v >= 100) & (v < 100p
0872デフォルトの名無しさん
垢版 |
2020/12/24(木) 11:27:11.76ID:h4Gph9I0
>>871
途中で送ってもうたorz

((v >= 100) && (v < 1000))のが気休め速い感じだったな。
あとLUTもほぼ変わらん。LUTはもう少し複雑な計算で、
かつキャッシュにテーブルが入ってくると鬼速だろうけど。

単純な比較のみだからあまり速い方法ないのかもね〜
ダメ元で掛け算とビットシフトで/100する処理も試したけど
ちょっと遅くなったorz

つか、32bitマイコンだと100us周期程度の割り込みハンドラで
この水準まで自分は気にしないだす。
あとC++ならinline化とかその辺をまずチェックでしょうさ。
0873デフォルトの名無しさん
垢版 |
2020/12/24(木) 17:12:04.54ID:tg7gMCA8
>>872
if ((unsigned)v - 100u < 900u)
のが早くない?

テーブルは論外だ
アドレス計算コストの方が高そうだし
ROMサイズやキャッシュ汚染などの悪影響がある
0874デフォルトの名無しさん
垢版 |
2020/12/24(木) 19:53:19.25ID:9+0irhfK
if ((unsigned)v - 100u < 900u)
こういうのは減算とコンペア(実質減算)の2回の演算が常に走るから必ずしも速くないんじゃないかな。
&&で繋ぐ方がショートサーキットが働いて1回で済む場合がある。
演算で0との比較に落とせるなら別だけど。
0876デフォルトの名無しさん
垢版 |
2020/12/24(木) 21:38:01.43ID:B83YCBUh
比較がボトルネックってのは本当だろうかとは思わなくもない
まあ、データ転送とか切り詰めまくって残すは比較のみ、ってのもありうるけど
0877デフォルトの名無しさん
垢版 |
2020/12/24(木) 21:38:20.67ID:X8ie3AzF
整数の減算は非常に高速
条件分岐は遅いし分岐予測を汚染する

コンパイラの最適化を見てると良い
範囲判定は大抵>>873のようなコードになる
0878デフォルトの名無しさん
垢版 |
2020/12/24(木) 21:41:03.65ID:X8ie3AzF
コード的には普通に
if (100 <= x && x < 1000)
と書いておけば良い

コンパイラが最適化するから

x/100を比較するのは
意味的にも意味不明だし
速くなることもない
0879デフォルトの名無しさん
垢版 |
2020/12/24(木) 21:51:18.77ID:X8ie3AzF
ISRの最適化なら

レジスタを節約して待避する数を減らすとか
レジスタバンクを使ってレジスタを切り替えるとか
RAM上で実行するとか
割り込みを許可せずに高速化とか(MIPSの場合)
まあ色々とチューニング出来る余地がある

小規模DSPなんかだと
いまだにISRをアセンブラで書いたりする
0880デフォルトの名無しさん
垢版 |
2020/12/25(金) 14:04:51.84ID:L6KY61Ck
バンク切り替えテクニックですか。
むかしのインターフェース誌っぽいですね。
0882デフォルトの名無しさん
垢版 |
2020/12/25(金) 20:23:57.32ID:KGl9PDWX
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>{});がどちらを呼ぶか規格で決まってる?
0884デフォルトの名無しさん
垢版 |
2020/12/26(土) 00:14:55.00ID:biNpl0R5
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>

だとだめなのだろうか?
誰か教えて下しあ
0885デフォルトの名無しさん
垢版 |
2020/12/26(土) 00:40:10.65ID:3VlCU3bq
>>884
上のコードと下のコードの RecursiveMapperType の定義はまったく同じに見えるんだけど、何が違うの?
0886デフォルトの名無しさん
垢版 |
2020/12/26(土) 00:50:04.37ID:biNpl0R5
>>885 さん
すみません。
下の方のRecursiveMapperTypeですが継承元消し忘れてました。
下のようなkたちです
struct RecursiveMapperType
{
RecursiveMapperType(){}
};
using RecursiveMap = std::map<std::string, RecursiveMapperType>
0888デフォルトの名無しさん
垢版 |
2020/12/26(土) 15:10:58.71ID:3VlCU3bq
>>886
それじゃ全然機能が違うっていうかその RecursiveMap 何の役にも立たないでしょ。
元の RecursiveMapperType の機能が理解できてないだけか。
0889デフォルトの名無しさん
垢版 |
2020/12/26(土) 16:40:20.18ID:vGzfsLf/
再帰的な構造を定義したくて自分自身の型を含めたものを継承してるわけで
それを実現するには前方宣言するしかない
というね
0890デフォルトの名無しさん
垢版 |
2020/12/26(土) 17:13:57.40ID:UNoc468U
再帰的なコンテナは、フィールドが出来た時点で破綻するのでは?
0892デフォルトの名無しさん
垢版 |
2020/12/27(日) 06:31:05.42ID:QkMmRpj8
C++23に持ち越された契約は何が変わるんだろね。
0893デフォルトの名無しさん
垢版 |
2020/12/27(日) 17:59:23.18ID:wQ5c+q6H
ありがとうございます。なんとなくイメージできました。

コードの設計ってまだよくわからないのですが、
再帰処理のためにこうするのって比較的普通なことなんですか?
0894デフォルトの名無しさん
垢版 |
2020/12/27(日) 18:23:25.49ID:tp3tetyk
>>893
知らんよ。
普通かどうかなんて気にしてどうするの?ここで名無しの誰かに yes/no 答えてもらって何か意味ある?
0895デフォルトの名無しさん
垢版 |
2020/12/27(日) 18:33:52.26ID:7Rx7y5wp
>>893
STLのクラスを継承して階層構造を実現するテクは応用編って感じがする
もっと基本的なやり方をするならデザパタのcompositeパターンを使う
とかかね
0897デフォルトの名無しさん
垢版 |
2020/12/27(日) 18:49:43.74ID:QkMmRpj8
ヘネパタ、パタヘネ、デザパタ。
0898デフォルトの名無しさん
垢版 |
2020/12/27(日) 22:11:00.35ID:QkMmRpj8
newのコストは気にされますが、deleteのコストは見逃されがちです。
0899デフォルトの名無しさん
垢版 |
2020/12/28(月) 02:23:23.12ID:ibU6N4ur
あるクラスのコンストラクタのデフォルト引数を変更するときってどうしたらいいの?
オーバーロードすれば良い?
■ このスレッドは過去ログ倉庫に格納されています

ニューススポーツなんでも実況