C++相談室 part151

■ このスレッドは過去ログ倉庫に格納されています
2020/05/14(木) 11:53:25.59ID:ZPCfyTux
C++に関する質問やら話題やらはこちらへどうぞ。
ただし質問の前にはFAQに一通り目を通してください。
IDE (VC++など)などの使い方の質問はその開発環境のスレにお願いします。

前スレ
C++相談室 part150
https://mevius.5ch.net/test/read.cgi/tech/1584975873/
このスレもよろしくね。
【初心者歓迎】C/C++室 Ver.105【環境依存OK】
http://mevius.5ch.net/test/read.cgi/tech/1556142878/

■長いソースを貼るときはここへ。■
 http://codepad.org/
 https://ideone.com/

[C++ FAQ]
https://isocpp.org/wiki/faq/
http://www.bohyoh.com/CandCPP/FAQ/ (日本語)

テンプレここまで
2020/06/14(日) 09:32:29.33ID:MuaS91+w
>>346
シェルとかも含めたXAML UIの部分のこと言ってるんだろうけど
あれはC#からも呼び出せるだけのネイティブで実装されたAPI(WinRT)だよ
今の電卓なんかはまさしくわかりやすい例で、特例でコード公開されてて全部C++(/CX)だよ
新規に打ち出そうとしてるWinUIもC++(/WinRT)での実装

UWPアプリ単体で見ればC++だったりC#だったりまちまちだろうけど
今はXAML=WPF=C#のイメージは切り離した方が良い
2020/06/14(日) 10:00:52.61ID:g+gmh/oa
>>347
納得した
にしても以前の電卓よりはるかに動作が重い
呼び出し元より呼び出し先に重い何かがある気がしてならない
2020/06/14(日) 10:31:38.76ID:v+4IVp6H
>>335
王者の風格とか気品とか、真のC++使いだとか、そのキッズが喜びそうなワードばかり並べ立てて何がしたいの?
2020/06/14(日) 10:36:59.36ID:UiekgbQo
(精神的)キッズが喜びたがってるのだろう
2020/06/14(日) 10:59:07.21ID:fGEYrFA/
確かに「王者の風格」がでてきたときは0.5秒くらい「えっ?」てなった
2020/06/14(日) 10:59:49.90ID:v+4IVp6H
>>338
プログラムの実装時の労力は言語だけでなく作る対象によっても変わるからケースバイケースだけど、言語の習得の労力で言えば、C++でまともな実用的なプログラムを作れるレベルに達するのは他の言語に比べて大変だよ。
もし今現在まったくプログラミングの経験がないなら、C++よりC#から始めた方がいい。
C#で速度がでないことを心配するなら、C#で作ってどう改善しても速度が足りないとなってからC++を学習してC++に移植する方がトータルでは早くできそう。
そもそもC#では速度的に厳しいような難易度の高いプログラムを、未経験者がいきなりC++で作り始めることはかなりこんなんだと思うぞ。
2020/06/14(日) 11:01:19.61ID:u20vDDhC
コードの王子さま「まだまだだね」
2020/06/14(日) 12:21:48.10ID:7AEk3bXh
孤高だからな
2020/06/14(日) 13:07:15.05ID:8/gzWF83
>>322,>>339は(ある程度)事実だろ
2020/06/14(日) 15:06:28.05ID:CHdP3JGu
>>347
>今の電卓なんかはまさしくわかりやすい例で、特例でコード公開されてて全部C++(/CX)だよ
>新規に打ち出そうとしてるWinUIもC++(/WinRT)での実装

C++/CX はC++ではない。
それが遅い原因だ。
C++/CXを勝手にC++と思ってしまう人が出て本物のC++は迷惑。
2020/06/14(日) 15:42:22.25ID:CHdP3JGu
>>341
>C : 15
>C++ : 75

もともと、C++は、C with class 程度の意味で現れて、それで人気が出た。
その時は今ほど複雑でなく、Cではメモリー解放 free() を全部完全にプログラマが
書かなければならなかったところと、C++のデストラクタを使えば、ほぼ自動化することが出来た。
これにより、C++はCよりはメモリー安全になった。
型をC以上に厳密にすることで、コンストラクタとデストラクタの呼び出される回数が、ほぼ必ず同じに
なるように設計されていた。
キャスト構文を使わず、それぞれのデストラクタの中で、子供のオブジェクトに対する delete 文を
書き忘れない限り、ほぼ、コンストラクタとデストラクタは一対一に対応するので、
結果的にメモリーの解放間違いはほぼ無くせる設計になっていた。
これが、(恐らく)後になって RAII という言葉で語られるようになっていった。
また、クラスメンバに対しprotected属性が使えることも安全性を高めた。
さらに、Cでは実行段階で関数を超高速に切り替えるためには関数ポインタを使うことが必須であったが、
C++では仮想関数でそれを行うことが出来るようになり、間違いを減らすことが可能になった。
クラスの継承の概念は、既に作ったプログラムを少しずつ変化させることに役立つため、
プログラムを美しく設計できるようになった。

C++は今のバージョンは難しく見えるが、もともとはCを安全にすることにとても役立つものであった。
2020/06/14(日) 16:14:13.31ID:PqSUj3Py
「本物のC++」であるかどうかと速度は直接関係はないと思うが
2020/06/14(日) 16:48:51.00ID:p2S0rZ5U
>>357
>C++のデストラクタを使えば、ほぼ自動化することが出来た。

それ、全然「自動化」になっていないですよ…
2020/06/14(日) 17:11:05.05ID:CHdP3JGu
>>358
C++/CXは、メモリ関連で本物のC++とは異なったやり方をしている。
C++が速いのはまさにメモリ関連であるのだから、ソースの書き方が似ていると
しても、そこを変えた言語で書いたプログラムの速度がC++と同じであるとは
とても言えない。
2020/06/14(日) 17:28:22.41ID:u+r3XtR9
この狂人C++/CXをC++/CLIと勘違いしてないか?
2020/06/14(日) 18:05:23.75ID:UiekgbQo
デストラクタをまともに設計できる奴があんまおらんからな。
てか資源解放てインスタンスの種類よりも生成したシチュエーションによることのが多いし
シチュエーション事に開放メソッド選ぶ方がわかりやすい。
だからgoではdefer文による解放なんだろ。
363デフォルトの名無しさん
垢版 |
2020/06/14(日) 18:12:49.93ID:iYtMGgBJ
>>349
そらキッズを説得するためだからよ。
2020/06/14(日) 18:16:02.14ID:CHdP3JGu
>>362
ファイルハンドルの様な「資源」は、デストラクタによる解放は実は向いてない。
メモリーが向いている。
もともと、C++のデストラクタは、メモリー安全のためが主目的であったと
言っても過言ではなく、RAIIの R = Resource というのは、変な話。
2020/06/14(日) 18:29:52.90ID:PqSUj3Py
>>364
全く逆だなぁ。
資源のように解放するタイミングが比較的重要なものこそデストラクタが向いているだろう。
メモリだけならGCでも全然問題ないし。
2020/06/14(日) 18:36:46.54ID:RsfUA2Vq
int と long long の和って long long ですよね?
int と double の和も double ですよね?
こういうのって大きいデータ型にキャストされると思って良いですか
367デフォルトの名無しさん
垢版 |
2020/06/14(日) 19:18:11.35ID:VVffaeyk
タイルマップエディタを作る場合はC++とC#どちらがいいですか?
2020/06/14(日) 19:26:48.64ID:v+4IVp6H
>>366
基本的にその考え方であってる。
細かいところは汎整数拡張でググってwikipediaを見てくるといいよ。
2020/06/14(日) 19:36:58.18ID:q7JXwjKs
>>367
どっちでもいい
どうせほとんどは途中で挫折するんだし、苦労して作ったところで現実には誰にも使われずに消えていく
しかしその努力は決して無駄になるわけではなく、君の中には多少なりとも技術と経験が残るだろう
目先ではなく、将来何がしたいのか、そのためには何を習得すべきなのかを考えなさい
370デフォルトの名無しさん
垢版 |
2020/06/14(日) 19:48:57.07ID:VVffaeyk
将来何をしたいか、わからないです
2dにopenglは必要ですか?
必要ならC++なんでしょう
2020/06/14(日) 19:53:15.45ID:irom8koH
2dにOGLは正直オプションだな。
OGLはグローバル規格だから、WindowsとかOSに縛られるということが少ない。
しかし、近年のGPUは3Dを基準に作っているからOGLを使った方が速度は出るかもしれない。
なお、OGLは特に言語は規定していない。
2020/06/14(日) 19:56:51.60ID:SBQSrEYR
ゲーム作りたいのか?
今時のゲーム開発ではそもそもOpenGLを直で叩く必要はまずなくて、Unityなどの開発スイートを使うのが普通だ
まあC#でいい
373デフォルトの名無しさん
垢版 |
2020/06/14(日) 20:05:56.73ID:VVffaeyk
じゃあエレクトロンで作るよ
2020/06/14(日) 20:21:24.84ID:irom8koH
その場合は、もしかしたらWEBGLかもしれんな。
375デフォルトの名無しさん
垢版 |
2020/06/14(日) 20:33:14.43ID:VVffaeyk
大事ナノは結局ロジックだと思うので(´・ω・`)速度とか考えずにやります
2020/06/14(日) 21:07:35.45ID:ZstiKk82
UE4はC++なので、ゲームを仕事にしたいなら、C++は使えた方がいい。
unityもスマホゲーや小規模開発でシェア大きいので、Unityで使うC#もやっておこう。
つまり、C#とC++両方を当然に使えるようになるべき。
趣味で作りたいだけなら、資料の多いunityでも、最近VE5の発表で熱いUE4でも、好きな方やればよい。
グラフィックエンジニアやりたいなら、DirectX12やVulcanにてをだしてもよいかもしれない。茨の道だがね
2020/06/14(日) 22:02:31.10ID:kf4Cc+ef
>>365
そうだよね
GC言語はある意味一番簡単なメモリの管理は自動化できても、それよりクリティカルなメモリ以外のリソース管理が悲惨なことになる
2020/06/14(日) 22:11:34.75ID:ye8ce71J
>>365
だから、あなたみたいなGC言語に慣れた人が多くなって、C++の本質が理解出来て
無くて RAIIなどといい始めたんだ。
ちがうんだよ、本来のデストラクタの主目的は。

デストラクタの中には、pure C の free() のように、本質的にはどんな場合に
呼び出しても失敗することが無いような関数だけを書くことが基本。
それを昇華すれば、deleteを書いても、絶対に失敗しないことになる。
これは数学的帰納法を理解できない人に入っている意味が分からないと思うが。

とにかく、デストラクタの役割も作られた目的も、メモリの安全な解放だったの
であって、リソースの開放のためでは無いので、リソースの解放をデストラクタ
の中に書くというのはさまざまな問題を生む。
2020/06/14(日) 22:29:21.16ID:ye8ce71J
>>365
>資源のように解放するタイミングが比較的重要なものこそデストラクタが向いているだろう。
少なくとも初期のころのC++は、そのようなことがデストラクタの主目的ではなかった。
今、GCでやっていることが効率が悪いことを見越して、かつ、メモリー安全性を確保するために
発明されたのがデストラクタだ。

数日前にも、ファイルハンドルなどのリソースをRAIIを使ってデストラクタで閉じようとすると、
失敗した時に対処できなくなるという非常に難しい問題が生じることが議論されていた。
メッセージボックスさえ出すことができないかも知れないのだ。
メッセージボックスを出そうとすることがむしろ仇となって、その瞬間に大切なデータが保存できて無い
アプリもろともダウンしてしまう可能性がある。

なぜそういうことがおきるかというと、もともと、デストラクタは、失敗する関数をそこに
含めることを想定していなかったからだ。
2020/06/14(日) 22:37:05.85ID:OGb6Unub
>C++の本質が理解出来て無くて RAIIなどといい始めたんだ。

RAIIって20世紀の頃の禿のお言葉なんだがw
2020/06/14(日) 22:52:30.07ID:ye8ce71J
Bjarne Stroustrup 氏の事を禿と言ってしまう人の人間性を疑う。
名前が覚えられないのか。
2020/06/14(日) 22:54:20.28ID:aLpfCXag
あら議論から逃げよったわw
2020/06/14(日) 22:58:03.93ID:MuaS91+w
妙だな? 誰も禿をびよーねとは言っていないのに・・・
2020/06/14(日) 23:03:05.44ID:PqSUj3Py
>>379
向いてる向いてないと元々の目的というのは直接関係ないな。
後半の話も、リソースの解放ができないということではなくてメッセージボックスを
出せないというだけでしかないし。
2020/06/14(日) 23:04:20.52ID:ye8ce71J
まあ、RAIIが、20世紀に考え出されていたのであれば、それはそれで良しとしよう。
でも、彼の頭の中でどうであったとせよ、当時の本を見れば、デストラクタの
説明としてほぼ必ずと言って、メモリ解放のために用いる例が書かれていたのだから、
C++を実用的な観点で見た時にデストラクタの一番の使い道はメモリ解放であった
ことは疑いの無い事実だろう。
2020/06/14(日) 23:09:16.33ID:hr1wykPX
>>385
誰も言ってくれてないから俺が言ってやるけど
お前は自分が見えてないよ
お前は人に教える立場ではなく
みんなに教えてもらってる立場なんだぞ
見てて恥ずかしいわ
2020/06/14(日) 23:13:56.65ID:OGb6Unub
>>385
ではここで太古から存在するハゲFAQを見てみましょう
https://www.stroustrup.com/bs_faq2.html#finally
388246
垢版 |
2020/06/14(日) 23:28:20.22ID:qmm3PCBI
>>246
に書いたけど、

デストラクタ中の例外の扱いについて、
More Effective C++ にも書いてある
389デフォルトの名無しさん
垢版 |
2020/06/14(日) 23:32:05.30ID:iYtMGgBJ
>>387
英語じゃねーか、日本語で書けよ。
2020/06/14(日) 23:57:28.27ID:ye8ce71J
アメリカ人は馬鹿だから参考にならない。
彼らのために世界中の生産性が下がっている。
2020/06/15(月) 00:10:53.34ID:Bn8xL7m+
禿先生はデンマーク人だぞ
2020/06/15(月) 00:13:02.53ID:1aJEphkT
>>389
王者の気品とか言っちゃう奴の日本語よりはまともな人の書いた英語の方が遥かに読みやすいし、内容の価値は比べるまでもないw
2020/06/15(月) 00:23:21.40ID:94IDrwxi
以上、本日のASDLおじいちゃん演説会でした
2020/06/15(月) 00:56:17.21ID:Hw5ljvB7
で、本物のC++はどうやったら食べられるのですか
2020/06/15(月) 02:02:25.91ID:oHOmQwtH
ドラえもんの暗記パンで
2020/06/15(月) 04:52:38.04ID:1aJEphkT
>>393
ASDLって何だ? ASDのことだろうか。
まさかADSLとごっちゃになってるんだろうか。
ホントに英語はまったくダメなんだな。英語の方が読みやすいなんて言って悪かったよ。
2020/06/15(月) 09:43:39.22ID:Q9IHrxmr
std::listやvector,map,unordered_mapなどのコンテナのイテレータについての質問です
コンテナのある要素を指すイテレータを保存してるときに、
そのコンテナに対して変更が加えられたとき、保存したイテレータは有効なのでしょうか??

例えば、元の要素が削除されたら、無効になるのは想像つきます
例えば、前後に別の要素が追加されたら、保存したイテレータは元の同じ要素を指してる保証はあるのでしょうか??

std::listはリンクリストなので、前後に要素を追加されても影響受けなさそうですが?
std::vectorはインデックスで管理してるとダメそう?
std::mapは?
2020/06/15(月) 10:08:43.12ID:w4yns3wG
イテレータが無効になる場合はコンテナの種類と操作によって決まっているのでまともな解説にはちゃんと書いてある。
例えばvectorのinsert()はストレージの再確保が行われなければinsertした場所より前の要素を指すイテレータは無効にならないといった具合。
2020/06/15(月) 10:13:02.37ID:Q9IHrxmr
>>398
https://en.cppreference.com/w/cpp/container
英語の方見たらイテレータの無効化条件書いてありました
ありがとうございます
2020/06/15(月) 12:16:11.97ID:LBP04AxD
>>399
日本語のほうにも書いてあるような?
https://ja.cppreference.com/w/cpp/container#.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
401デフォルトの名無しさん
垢版 |
2020/06/15(月) 14:06:35.72ID:iqqqiJ5Y
デストラクタで例外を出す可能性があるクラス Hoge について

---- A.cpp
Hoge hoge;
int main(int argc, char **argv)
{
// hoge を使う
return 0;
}
---- A.cpp ここまで

---- B.cpp
int main(int argc, char **argv)
{
Hoge hoge;
// hoge を使う
return 0;
}
---- B.cpp ここまで

B だと例外補足されるというか表示されるけど
A だと握り潰されてプロセス終了する(例外出てても気付けない)?
2020/06/15(月) 14:12:45.65ID:+GKLccgq
はちみつ餃子 さまを筆頭とする方々にお答えしていただけることを期待しております。

std::forward()がどうやって実装されているかを調べるため、
MSのオープンソースのSTLのソースの「STL-master」の中の type_traits
というのを見ていたのですが、仕組みが完全には分かりません。
以下の1つ目のforwrd()は、左辺値参照で受け取るまでは分かりそうなのですが、
その後、return static_cast<_Ty&&>(_Arg) としているのに、結果は、左辺値に
なっていなければ、forward()の使用に合わないはずですが、なぜ、
右辺値参照にcastしているのに、左辺値参照のままなのでしょうか?

/* 左辺値を受け取る forward() のテンプレートらしいですが、
  _Arg が左辺値参照ならば(?)、static_cast<_Ty&&>(_Arg)
  と cast しても、右辺値参照になるとるは限らない??? */
template <class _Ty>
_NODISCARD constexpr _Ty&& forward(
  remove_reference_t<_Ty>& _Arg) noexcept { // forward an lvalue as either an lvalue or an rvalue
  return static_cast<_Ty&&>(_Arg);
}

// 右辺値を受け取る forward() のテンプレートらしいです :
template <class _Ty>
_NODISCARD constexpr _Ty&& forward(remove_reference_t<_Ty>&& _Arg) noexcept { // forward an rvalue as an rvalue
  static_assert(!is_lvalue_reference_v<_Ty>, "bad forward call");
  return static_cast<_Ty&&>(_Arg);
}

template <class _Ty>
_NODISCARD constexpr remove_reference_t<_Ty>&& move(_Ty&& _Arg) noexcept { // forward _Arg as movable
  return static_cast<remove_reference_t<_Ty>&&>(_Arg);
}
2020/06/15(月) 14:46:55.44ID:WVo0Ka65
>>402
正確なルールを説明するとなると長くなる (というか私もそんなに入り組んだところまで把握してない) んだが、
「参照の参照」を作った時に調整されるルール reference collapsing によるものだと思う。
左辺値参照から右辺値参照を作ろうとしたときには左辺値参照に調整される。
2020/06/15(月) 15:04:09.59ID:+GKLccgq
>>403
回答有難うございます。

一生懸命調べたところ、こんな記述を見つけました。Tがオブジェクト型の場合、(T &&)x のように cast すると、
結果は、右辺値にならずに xvalueになるようです。
でもそこから先は理解できてません。

https://stackoverflow.com/questions/40801765/is-it-an-rvalue-or-lvalue-after-a-cast

From expr.cast (this is applicable from C++11 and later)
C++ 11 以後の場合 :

The result of the expression (T) cast-expression is of type T.
式「(T)cast-expression」の結果は、T 型である。

The result is an lvalue if T is an lvalue reference type or an rvalue reference to function type and an xvalue if T is an rvalue reference to object type;
Tが関数型への左辺値参照/右辺値参照の場合は、結果は 左辺値で、
Tがオブジェクト型への右辺値参照の場合は、結果は xvalue である。

otherwise the result is a prvalue.
そのどちらでも無い場合、結果は、prvalue である。
2020/06/15(月) 15:11:00.42ID:UmY/I/0X
>>404
今後のために、
先輩指名で相談に行って
あなたの説明よりネットにはこんなの書いて有りますけど?
なんてのは失礼でイラッとするからやめときや
2020/06/15(月) 15:15:51.75ID:kn0xQdMp
より詳しい説明が出るのは役に立つんだから別にいいだろ

それよりもはちみつごときに様つけたりここの住人の筆頭にするな
2020/06/15(月) 15:17:44.93ID:WVo0Ka65
>>404
xvalue は rvalue の一種。
2020/06/15(月) 16:19:05.98ID:+GKLccgq
>>407
lvalue, xvalue, prvalue は排反集合なのですが、
glvalueとrvalueは、正確に

#define IS_GLVALUE(X) (IS_LVALUE(X) || IS_XVALUE(X)) // glvalue は、lvalue と xvalue の和集合
#define IS_RVALUE(X) (IS_PRVALUE(X) || IS_XVALUE(X)) // rvalue は、 prvalue と xvalue の和集合

なので、rvalueであっても、xvalueで無い場合がありえます。
それは、prvalueです。
2020/06/15(月) 16:32:37.00ID:+GKLccgq
>>406
>それよりもはちみつごときに様つけたりここの住人の筆頭にするな
このスレでは、彼が一番C++に詳しいと思うんです。
もしかしたら日本の中でもかなり詳しい人の内に入るのではないでしょうか。
2020/06/15(月) 17:00:27.16ID:+GKLccgq
>>408
>なので、rvalueであっても、xvalueで無い場合がありえます。
このことは、正しいのですが、
#define IS_RVALUE(X) (IS_PRVALUE(X) || IS_XVALUE(X)) // rvalue は、 prvalue と xvalue の和集合
によれば、
xvalueであれば 必ず rvalue ではあるので、
「xvalue は rvalue の一種」
という命題は必ず真で、はちみつ餃子さんのおっしゃっていることは正しいと思います。
rvalueが動物、xvalueが犬、であるような関係になります。
動物(rvalue)であっても犬(xvalue)で無い場合がありえますが、
犬(xvalue)であれば必ず動物(rvalue)であり、犬(xvalue)は動物(rvalue)の一種です。
2020/06/15(月) 17:03:05.14ID:+GKLccgq
「xvalue は rvalue の一種」でもあり、
「xvalue は glvalue の一種」でもあるのですね。
2020/06/15(月) 17:11:13.40ID:WVo0Ka65
>>405
疑問が深まったら掘り下げるのは別にいいんじゃね。 根拠も提示されてるし。

>>409
ワイは趣味プログラマやで。
実務家が言語仕様の詳細に興味がないのもよくあることなので、
プロのプログラマが仕様に詳しいとは限らんけど、
平均的には日常的に C++ でプログラミングしているやつの方が詳しいよ。 当然に。

>>408
あれっ、そうか。 カテゴリに関しては俺の間違い。
で結局は >>403 で述べた通り reference collapsing が適用されるってだけだと思う。
https://timsong-cpp.github.io/cppwp/n3337/dcl.ref#6
2020/06/15(月) 17:18:57.93ID:WVo0Ka65
いや、なんか違う気もしてきた。
わかんね。
2020/06/15(月) 18:34:21.52ID:+GKLccgq
>>412
>平均的には日常的に C++ でプログラミングしているやつの方が詳しいよ。 当然に。
C++は、何十年も前に既に完成している言語なので、実態はわかりませんが、仕事をC++を使っている人でも、はちみつ餃子さんのようには新しい仕様を知らない人の方が多いのではないかと思うのです。
2020/06/15(月) 20:04:29.90ID:fMEeoq9p
はちみつ餃子 さまを筆頭とするはちみつ餃子さまにお答えしていただけることを期待しております。

普段どんな仕事をしてるの?
2020/06/15(月) 20:05:26.73ID:+GKLccgq
>>404
「The result is an lvalue if T is an lvalue reference type or an rvalue reference to function type and an xvalue if T is an rvalue reference to object type;」
の部分の訳が一部間違っていて、正しくは、
「Tが左辺値参照型か、または、関数型への右辺値参照の場合は、結果は 左辺値で、
 Tがオブジェクト型への右辺値参照の場合は、結果は xvalue である。」
ということのようです。

結果として、>>402 の return 文のオペランドの
static_cast<_Ty&&>(_Arg)
の部分は、
1. _Argの型が左辺値参照型の場合、左辺値(i & !m)
2. _Argの型が右辺値参照型の場合、xvalue(右辺値の一種, i & m)
となるようです。
2020/06/15(月) 20:13:24.30ID:ZNXm/M6v
自分のレスにレス返すスタイルなんなの
自分の日記帳でやれよ
2020/06/15(月) 20:48:28.91ID:hnmQwUn9
これ前の人だよね
2020/06/15(月) 21:31:20.35ID:bSwpQKjB
結局答えられないんですねの人?
2020/06/15(月) 21:44:07.48ID:Q9IHrxmr
また、質問します。
アプリでunordered_mapやunordered_setのコンテナ10個くらい使うのですが問題はキーの型が可変長でstd::stringで結構長いことです
具体的にはキーはファイルパスとかになるのですが
で、頻繁にコンテナを使用します
ファイラーみたいなアプリを想定して

このとき、キーをstringにするとコピーなどのオーバーヘッドが発生?すると思いますがさすがにこのレベルは気にした方がよい?
2020/06/15(月) 21:48:49.59ID:Q9IHrxmr
ユーザーがカレントフォルダ移動したり、ファイル一覧のリストビューをスクロールするだけで走ります


で、きにする場合はキーをstd::shated_ptrでくるめばいいんですかね?他に方法ありますでしょうか?
2020/06/15(月) 22:01:06.47ID:LBP04AxD
>>420 効率は実測が基本。
2020/06/15(月) 22:17:50.72ID:Bn8xL7m+
100万文字のstringをキーにしたって、unorderedの内部で扱うのはハッシュなんだから挿入や検索の速さは変わらん(ハッシュ計算のコストを除く)
そのファイラーが糞重いんだったら原因はそこじゃないと思うぞ
2020/06/15(月) 22:52:38.98ID:Q9IHrxmr
ありがとうございます
>>422の言う通り最終的は実測でしょうが、キーをstringにしたときのキーのメモリコピーのオーバーヘッドを気にしてました
が、よく考えてみますと実際にキーのコピーが発生するのは実際に要素を挿入するとき1回だけっぽいですね

findメソッドやcountでキーを渡しますがキーを参照で渡しますし、hash関数も参照でキーの値を受けとりますし
2020/06/15(月) 23:00:46.83ID:Q9IHrxmr
キーのコピーの頻度そこら辺を想像したことなかったので、びびってましたがびびる必要なかったぽいですね

ということ、普通にstringをキーに実装してみます
2020/06/15(月) 23:00:50.65ID:WVo0Ka65
>>424
string はムーブ対応してるんで所有権を渡してしまうなら文字列全体のコピーはしないよ。
2020/06/15(月) 23:12:46.11ID:Q9IHrxmr
>>426
なるほど、findやcountの場合はキーの値を実際にコピーする必要ないから、&&の引数のオーバーロードはないが、insertの場合は&&の引数で、所有権移せるバージョンもあるんですね
2020/06/15(月) 23:14:22.14ID:hnmQwUn9
この人がどうかは知らないけど
スクリプト言語あがりはstring + mapばっか使うんだよね
万能さはわかるけどさ
それで効率が〜とか
どうなのそれw
2020/06/16(火) 00:10:13.43ID:1HqJhS8P
ワイはもうおっちゃんやから小さい単位で型を作って名前を付けておかんと何をしよったかわからんようになるんやが、
文字列三昧で上手いことやれてまうやつはどういう脳みそをしとんや……。
と疑問に思ったこともあったんやけど、大抵の場合はうまいことやれとらんかった。
2020/06/16(火) 00:48:04.50ID:i3Et6pFy
プログラマ2年目だけど全然クラス作れんワイ低みの見物
責務責務いうけどどっからどこまでが責務やねん
431デフォルトの名無しさん
垢版 |
2020/06/16(火) 01:42:35.85ID:YM27wSPO
いや、おそらくその設計間違ってるな。
2020/06/16(火) 05:42:11.77ID:5RaFaaPW
std::string は参照カウントになってる場合もあるでしょ。
オブジェクトをコピーしても長さに応じたデータコピーが発生するとは限らない。
代わりに短い文字列ばっかりでも同じだけ重い可能性もあるんだが。
2020/06/16(火) 08:52:22.88ID:1HqJhS8P
>>432
ちゃんとした実装なら短い文字列ではヒープアロケーションが発生しないような最適化 (いわゆる SSO) が入ってるよ。
2020/06/16(火) 08:59:33.85ID:7rFOsosY
gccは参照カウントなstringは課題があるからやめたって10年以上前に聞いた気がするけど今はどうなんだろ
2020/06/16(火) 13:38:01.19ID:Ea3gt1wL
>>123
>100万文字のstringをキーにしたって、unorderedの内部で扱うのはハッシュなんだから挿入や検索の速さは変わらん(ハッシュ計算のコストを除く)
厳密に言えば変わります。
データの個数がM、キーの文字数がNの場合、検索に掛かる時間は、
ハッシュを遣わなくて単純に比較した場合は、
O(MN)
となりますが、ハッシュ法の場合でも、
O(M + N)
となるので、掛け算と足し算の違いは有りますが、キーの文字数をいくら長くしても検索時間が増えない、というようなことはありません。
2020/06/16(火) 15:27:53.17ID:VeSUiyGP
>>430
クエリとコマンド、リードとライトでとりあえず分けるとこからやったらええ
2020/06/16(火) 15:55:59.04ID:1HqJhS8P
>>430
責務なぁ……。

俺はとにかく名前で考えるようにしてるよ。
名前を付けたい単位に分けて、それを書いている内に名前を付けたい部分が出来たら括り出して……
という風に繰り返してたら (少なくとも自分にとっては) だいたい使いやすいデザインが出来てる。
名前を付けたらそれの役割ってのはほとんど自明だったりするし。

ぼんやりした構造って頭に残り難くて何をやってたかわけわからんようになるので、
名前を付けるってのはかなり大事なことだと思う。
2020/06/16(火) 18:27:56.96ID:HoWpcnpR
>>435
O(M+N) って、ハッシュ計算のコストを含めたうえでの最悪計算量でしょ。
ハッシュ計算のコストを除いた平均計算量を O(1) にすることも可能なのがハッシュの利点、というのが一般的かと。
https://ja.wikipedia.org/wiki/%E3%83%8F%E3%83%83%E3%82%B7%E3%83%A5%E3%83%86%E3%83%BC%E3%83%96%E3%83%AB
> ...検索や追加を要素数によらず定数時間O(1)で実現する。...
2020/06/16(火) 18:49:47.04ID:Ea3gt1wL
>>438
キーはそんなにバイト数が長く無くて、常識的にはある程度で上限が有る事が多いので、通常はO(1)と書いてあるだけです。
なぜかというと、ハッシュ値で大体は特定できても、最後、キーが完全一致していることを確認しなくてはなりませんが、
その時に文字列の比較のために、文字列の文字数であるところのNに比例した時間が掛かるためです。

例えば、キーの文字列の長さNが、1GBだとすると、文字列比較のために1*10^9程度のループが必要となります。
2020/06/16(火) 19:19:02.88ID:HoWpcnpR
>>439
そっか。一致比較が必要になる操作も確かに多いね。
N はわかったんだけど、 M もやっぱり最悪ケースの話ってことで合ってる?
「通常はO(1)」って言ってるし。
2020/06/16(火) 19:21:15.40ID:uOZIHf/t
スレ立てるまでもないスレにも同じようなこと書いたのですがすみません

巨大なファイルを読み込んで書き出すプログラムを書いています
time1, data1-1, data2-1, data3-1......datan-1
time2, data1-2, data2-2, data3-2......datan-2

みたいな構造が延々と続いています

でこれをdataごとに
data1.csv
time1 data1-1
time2 data1-2

ってそれぞれ書き出して分割する感じなんです

vector<ofstream&> files;
for (auto filename : filenames)
{
2020/06/16(火) 19:24:51.88ID:uOZIHf/t
失礼途中で送信してしまいました。

vector<ofstream&> files;
for (auto filename : filenames)
{
ofstream temp(filename, ios::out);
files.push_back(&temp);
}

こんな感じでofstreamの配列を作ってあとはそれぞれにデータを入れていこうとしたのですが
アクセス違反になります。スコープの外に出たらofstreamは勝手にcloseされる?そうなのでそのせいかなと思っています
複数のファイルに対して順々にデータを書いていきそれをループするのってどうしたらいいでしょうか
2020/06/16(火) 19:29:01.32ID:zbVOEmpz
答え分かってんならちゃんと実体を外に持たせなよ
vector<ofstream> files;
for (auto filename : filenames)
{
ofstream temp(filename, ios::out);
files.push_back(std::move(temp));
}
2020/06/16(火) 20:59:11.88ID:i3Et6pFy
通常はO(1)(で見積もっときゃまぁ大きくは外れない)
2020/06/16(火) 22:57:05.95ID:EUOlqdFN
業務でC++やることになりました
どうせなら体系的に学ぼうと思い、本を買おうと思いますがおすすめありますか?
CとC#の経験はあります
Cは組み込み開発での利用に、C#はデザインパターンを少しは活用出来る程度のレベルです
2020/06/16(火) 23:21:49.71ID:yU3B6kSM
>>435
キーの文字数Nはプログラムがビルドしおわったら変わらないのだから実質定数なのであって、
結局O(M)になるのでは…
(任意のxについて x + 定数 < a * xを満たす定数aを見出せるからオーダー表記の約束によりO(M+(定数)) = O(M)ェ、

しかもこの場合のMはデータの個数に比例するとわいえ、一般的はハッシュテーブルなら衝突しない限り
1回のテーブルアクセスで目的のエントリにたどり着くから、実際にはデータの個数÷ハッシュテーブルサイズ(エントリ数)
となるから衝突が無視できる(エントリ選択に統計的に偏りがなく、かつハッシュテーブルサイズが十分おおおきい
ならO(1)と逝って良いキモス、
■ このスレッドは過去ログ倉庫に格納されています
5ちゃんねるの広告が気に入らない場合は、こちらをクリックしてください。

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