[過去ログ] C++相談室 part150 (935レス)
上下前次1-新
このスレッドは過去ログ倉庫に格納されています。
次スレ検索 歴削→次スレ 栞削→次スレ 過去ログメニュー
1: 2020/03/24(火)00:04 ID:YFRNwZnv(1) AAS
C++に関する質問やら話題やらはこちらへどうぞ。
ただし質問の前にはFAQに一通り目を通してください。
IDE (VC++など)などの使い方の質問はその開発環境のスレにお願いします。
前スレ
C++相談室 part149
2chスレ:tech
このスレもよろしくね。
【初心者歓迎】C/C++室 Ver.105【環境依存OK】
2chスレ:tech
■長いソースを貼るときはここへ。■
外部リンク:codepad.org
外部リンク:ideone.com
[C++ FAQ]
外部リンク:isocpp.org
外部リンク:www.bohyoh.com (日本語)
テンプレここまで
809(1): 2020/05/09(土)14:01 ID:8wHk9BWj(7/11) AAS
>>808
多分、orz
計算機科学や実際のプログラムの実装は複雑怪奇なので、
病的な反例が何かあるかも((((;゚Д゚))))ガクガク
810: 2020/05/09(土)14:22 ID:KZFWOt7Z(2/9) AAS
>>801
それはメモリバリアのことですよね
つまりCPU内のリオーダーの制御で
lockからunlcokまでメモリアクセスはその外にリオーダーされることがない
>>800 で気にしてるのはそれではないです
レスわけます
811(4): 2020/05/09(土)14:32 ID:KZFWOt7Z(3/9) AAS
>>802
> >>800
> >>774のコードの全体の当否はおくとして
> while()の中でlockしているのであればlockされるブロックに出入りする際に
> >runningは毎度メモリから読まれる
> が実現されるからrunningフラグはvolatile無しでもむ無問題、
一度目はメモリから読まれるのは確実だと思います
ただループの場合、2度目のリードからはコンパイラが最適化をかけて
一度目の値を使いまわす可能性があると思います
void loop()
{
unique_lock lock(mtx);
auto r = running
while (r) {
....
}
}
と置き換えてしまう可能性があるのでは?ということを心配しています
私のC言語開発の経験ではこの場合はvolatileにするのが鉄則でした
c++のコンパイラはかしこくrunningは都度メモリから読み出すべしと判断していると
なるとその判定はどうやって行っているのでしょう?
一律にローカル変数以外はメモリから呼び出すわけではないと思います
(それだとかなり性能が落ちると思います)
812(2): 2020/05/09(土)14:56 ID:8wHk9BWj(8/11) AAS
>>811
コンパイラ視点で見れば中身のわからないcond.wait()と言う関数呼び出しが
グローバル変数runningに対する副作用を持たない(値を書き換えない)ことの保証が無いから、
cond.wait()をループ外にくくりだす最適化が行われることは普通は無い。 --- (A)
また、ソースコード上cond.wait()を呼び出した後にrunningを参照する箇所があれば、
普通はかならずメモリからrunningを読み直すコードが吐かれる --- (B)
普通でない場合というのはコンパイラがcond.wait()メソッドの中身まで知っていて
runningに対する副作用が無いと結論付ける場合が考えられるが、
それでもcond.wait()の中で
(1) メモリバリアを行っており、
(2) その意味をコンパイラが知っている
限り、コンパイラが「(cond.wait()呼び出しによる)runningに対する副作用が無い」と結論付けることはありえない --- (C)
というわけで、普通は(A)、(B)が成立するからrunningのvolatileは不要
(A)、(B)非成立な変に賢いコンパイラでも、(1)と(2)が成立するなら(C)が成立するからrunningのvolatileは不要
813(1): 2020/05/09(土)15:08 ID:1JWVR6vl(3/5) AAS
>>811
ループは>>791の方法で行くんじゃなかったの
814(2): 2020/05/09(土)15:08 ID:KZFWOt7Z(4/9) AAS
>>812
それはstd:::condition_variableを使った場合に限定していますか?
基本的にpthreadのwrapperだと思うのですが、仮にコンパイラがそれを特別扱いしているとすると
pthreadをダイレクトに使った場合はどうなりますか?
あと客観的な文献を示してほしいです
815(1): 2020/05/09(土)15:11 ID:KZFWOt7Z(5/9) AAS
>>813
そうですが別の話題なのでわかりやすく書きました
ただ >>791 もイベント処理中はunlockしておく必要があったのでそこは変えました
816: 2020/05/09(土)15:20 ID:1JWVR6vl(4/5) AAS
>>815
それだと>>811のコードでwhile(r) (あるいはwhile(running))ってなってるのがわからない
>>791だとwhile(true)の中でif(!running)ならbreakするって形でそもそもrunningは一回しか評価しないはず
817(2): 2020/05/09(土)15:38 ID:8wHk9BWj(9/11) AAS
>>814
>それはstd:::condition_variableを使った場合に限定していますか?
いいえ
>pthreadをダイレクトに使った場合はどうなりますか?
どう使うつもりかわわからんが、コンパイラに中身を知りようが無い関数の
呼び出しがループ内に生じる限り同じ話
>客観的な文献を示してほしいです
(1) 変数に対する副作用がある(かもしれない)関数がループ外にくくりだされないこと
コンパイラはソースコードをオブジェクトコードに翻訳する際、
ソースコードに書かれたアルゴリズム(有限ステップで終わる&非同期要素無し)の
動作結果を変えてはならない。この原則はコンパイラの教科書に書いてあるし常識と言っても過言ではない
で、変数に対する副作用がある(かもしれない)関数の不適切な最適化はこの原則にひっかかる
(2) 少なくともMSVCがメモリバリアの意味を知っている根拠
外部リンク:docs.microsoft.com
これ、VS2010までは非推奨ではなかったし、サンプルコードも載っていたが無くなってたorz
818(1): 2020/05/09(土)15:40 ID:VRhqXw8t(3/3) AAS
>>814
標準スレッドライブラリを使った前後の読み書きについては、
ライブラリ関数呼び出し( lock/unlock など)が提供するスレッドをまたぐ "synchronize with" 関係と
スレッド内での, "sequenced before/after" による前後関係とをつないだ
"inter-thread happens before" 関係(順序付け)に基づく挙動が規定されている。
外部リンク:timsong-cpp.github.io
>811 のような書き換えは許されない。
規格化以前の pthread などをダイレクトに使った場合は >>812 の挙げるような
「事実上問題にならない」に頼ることになり、これに volatile を加えても「事実上問題にならない」の
範疇であることに変わりはない。
問題の可能性が減ったり、実際に起こっていた問題の解決につながることはあっただろうけどね。
これについては「客観的な文献」といったものが無かったことも規格化の動機になっただろう。
外部リンク:isocpp.org
> - Machine model and concurrency ? provide stronger guarantees for and better facilities
> for using modern hardware (e.g. multicores and weakly coherent memory models). ...
819(1): 2020/05/09(土)16:27 ID:KZFWOt7Z(6/9) AAS
>>817
なるほど
つまりc/c++コンパイラの最適化において、
副作用がある(pure functionでない)関数があると、それをまたいだ
リオーダーや値の流用をすることはない
当然メモリバリアを張るcond(pthreadも含む)は副作用ありなので
これがループ中に存在する場合はrunningは毎度メモリから読み出されることになる
ということですね
非常によくわかりました
820(2): 2020/05/09(土)16:30 ID:KZFWOt7Z(7/9) AAS
>>817
しかし、この場合volatileが不要といえることはわかりましたが、
これはあくまで副作用あり関数の存在に依存しています
と考えると一般的にはvolatileはつけておく方習慣の方がやはり無難だと思いますがいかがでしょう?
(c++ならatomicに置き換えるとして)
821: 2020/05/09(土)16:33 ID:KZFWOt7Z(8/9) AAS
>>818
ありがとうございます
ちょっとこれを読み解くのは難しそうですね・・・
あとでじっくり読んでみます
822: 2020/05/09(土)16:41 ID:8wHk9BWj(10/11) AAS
>>819
レジスタに載ったままな変数の流用はともかく、
リオーダーは副作用がある(pure functionでない)関数をまたいでも特に阻害されないんじゃね;
リオーダーの効果はプログラムの実行に関して普通の状況では透過的なので、普通の状況でコンパイラがそれをやめさせる理由が無い
普通でない状況としては>>714みたく同一データに対する複数コアからの同時アクセスがありえるケース
(コンパイラが知りようが無い非同期事象が生じるケース)があるが、
これは(ユーザーコードかライブラリの)プログラマがメモリバリアを明示的に書き、
コンパイラが空気を呼んでその前後の変数の流用も抑止することで処置される
と思うが真実は知らん
気分としてはあくまで>>800の立場であって非同期の問題に関してはノーコメント
事実として出来上がったプログラムが正しく動いているなら問題ないのじゃガッハッハッハ、
823: 2020/05/09(土)16:43 ID:8wHk9BWj(11/11) AAS
訂正orz
誤: >>714 ==> 正: >>774
誤: >>800 ==> 正: >>809
824(2): 2020/05/09(土)17:00 ID:1JWVR6vl(5/5) AAS
>>820
複数スレッドで共有する変数を読み込む以上絶対にlockなりatomicなりを使うわけだから必ず副作用あり関数が存在する
825: はちみつ餃子 ◆8X2XSCHEME 2020/05/09(土)18:56 ID:MmeKQuXy(1) AAS
>>820
見かけ上の挙動が仕様通りだったらどうコンパイルしてもよいというのが言語としての基本的なルール。
外部リンク:timsong-cpp.github.io
昔は並列実行に関する動作モデルの既定がなかったので、
既定にないことをするプログラムを書いたときに
最適化で除去されたり順序が入れ替わったりしてもそれは仕様通りだったんだよ。
volatile はプログラムとして書いてある通りのことを (たとえ観測できなくても) 実際の動作にも
反映させろというヒントをコンパイラに伝えるものではあるけど、
言語仕様の記述に用いられる抽象機械と実際の実行環境が完全にマッピングできるわけでもない
から volatile が具体的にどう影響するかってのは分からん。
言語仕様外のことをするときのために用意されていると考えてもいい。
つまり、ロックやアトミックまわりの仕様で規定されていることなら volatile を付けようが付けまいが
その通りになるし、既定されていないことなら volatile を付けても言語仕様として得られる保証は何もない。
処理系として言語仕様以上の保証を付けているということはあるだろうけど。
826: 2020/05/09(土)18:58 ID:KZFWOt7Z(9/9) AAS
>>824
確かに、正しく排他制御しているのならばそれはいえそうです
827: 2020/05/09(土)19:14 ID:TBKnesgm(1) AAS
volatileは簡潔に言うとregisterの逆の作用だね
828: 2020/05/09(土)22:27 ID:IGvav/BT(1) AAS
volatileはコンパイラに、コード通り読み書きを行うコードを吐けと指示するだけ
CPUが勝手に順番を変えたりしないようにCPUに指示をする命令は別途行わなければならない
x86の場合は何もしなくて良い場合が多く
ARMの場合は追加しなければならない場合が多い
829: 2020/05/09(土)22:31 ID:TVkAIoUw(1) AAS
いいえ、単に昔からGCCが糞なだけです。
830: 2020/05/09(土)22:42 ID:G+eyUkVB(1) AAS
最近日本式のやつが再注目されてるじゃないか。
それは欧州式のやつのことじゃないか?
831: 843 2020/05/09(土)23:22 ID:NXsGMAUL(1) AAS
>>824
片方は書き出し、もう一方は読み出しだけなら排他制御しなくてもアトミックでありさえすれば大丈夫だし、そういう実装はそれなりにあるよ
832(1): 2020/05/10(日)02:46 ID:EdgxbLB4(1/2) AAS
可変長引数テンプレートから型の文字列を組み合わせて配列を定数化して取り出せるようにするために
以下のようなコードを書いたのですが、
template<typename ... ComponentsData> struct ComponentTypeGroup {
static constexpr std::size_t ComponentCount = sizeof...( ComponentsData );
static constexpr std::string_view TypeTexts[ComponentCount];
template<typename Type> constexpr void TypeGroupText( std::size_t _uIndex ) {
TypeTexts[_uIndex] = Detail::Nameof<Type>(); // 定数文字列を生成する関数です。
}
template<typename First, typename Second, typename ... ArgTypes> constexpr void TypeGroupText( std::size_t _uIndex ) {
TypeGroupText<First>( _uIndex );
TypeGroupText<Second, ArgTypes...>( _uIndex + 1 );
}
constexpr ComponentGroup(){ TypeGroupText<ComponentsData...>( 0 ); }
};
constexpr ComponentGroup()で「型指定子がありません」と出てコンパイルエラーが取れません。
何故このエラーが出ているのかがいまいちわからず、途方に暮れています。
誰かご教授いただけないでしょうか?
833: 2020/05/10(日)02:51 ID:KxiPn0ce(1) AAS
ComponentTypeGroupのtypoでなくて?
834: 2020/05/10(日)03:20 ID:s7BT3+bq(1) AAS
まずそのインターコンチネンタルホテルみたいな長ったらしい名前やめろ
835(1): 2020/05/10(日)03:25 ID:wE52EU/R(1/2) AAS
古いコードの一時的メンテのため、stdとstd::tr1をC++11で混在させて使う話なんですが、
元々C++11以前のコンパイラ用に書かれた
using namespace std;
using std::tr1::shared_ptr;
shared_ptr<Hoge> hoge = ...
みたいなコードをC++11でビルドすると、C++11には std::shared_ptr があり ambiguous エラーになりますよね。
最初 share_ptr を std::shared_ptr ということにしてビルドしようかと思ったら、ところどころ std::tr1::shared_ptr と
フル宣言してあり面倒なことが判明。なので shared_ptr は std::str1::shared_ptr とみなす方針に戻りました。
なので using namepace std; を保持しつつ shared_ptr を std::tr1::shared_ptr としてビルドしたいんですが、
それって可能でしょうか? 例えば using namespace std; で std::shared_ptr を除外するようなことってできます?
古いコードを出来るだけいじらずビルドしたい、というのが一番のポイントですw
836(1): 2020/05/10(日)03:46 ID:oMXEUzlE(1) AAS
単に#include<tr1/memory>してstd::tr1::shared_ptrのusingを消すんではあかんの?
新しいコンパイラではstd::shared_ptrとstd::tr1::shared_ptrって同じものでしょ
837: 2020/05/10(日)05:06 ID:wE52EU/R(2/2) AAS
>>836
using std::tr1::shared_ptrを取るとただのshared_ptrはstd::shared_ptrになります (using namespace std)。
すると今回の場合、
std::tr1::shared_ptr<Hoge> boge; // たまにちゃんと名前空間を使ってる宣言がある
boge = shared_ptr<Hoge>(new Hoge);
みたいなコードが駄目になるようですが。
std::tr1::shared_ptrとstd::shared_ptrはとりあえず名前としては違うんじゃないですか? 違うとコンパイラー
が認識しているように見えますが。
838(1): 2020/05/10(日)11:05 ID:sYQDYC6t(1/2) AAS
淫乱チンポメンタルヘルス?
839: ◆QZaw55cn4c 2020/05/10(日)11:14 ID:PNwCDTcQ(1) AAS
>>838
それ、面白いと思ったのですか?
840(3): 2020/05/10(日)11:25 ID:5OK5MvZd(1/2) AAS
>>835
これで全部 std::shared_ptr になるんじゃない?
namespace std { namespace tr1 = ::std; }
841: 2020/05/10(日)11:49 ID:sYQDYC6t(2/2) AAS
インサートチンポレンタルホテル!
842: 2020/05/10(日)12:12 ID:6Ru0pW3/(1) AAS
>>840
> namespace std { namespace tr1 = ::std; }
おお、これで std名前空間の中に tr1 のエイリアスを定義できる感じですか?
結果 std::tr1 は ::std -> std を指す、と。
843(13): 2020/05/10(日)12:19 ID:KGOVLWXM(1) AAS
>>832
constexpr ComponentGroup()の返り値がない。
constexpr void ComponentGroup()じゃない?
844(1): 2020/05/10(日)12:49 ID:uBqrUzQt(1) AAS
コンストラクタの綴り間違えているんじゃね?
何れにしろconstexpr static memberをコンストラクタやメンバ関数内で初期化は出来ないと思うが。
やるならstatic constexpr member関数の戻り値で初期化するとかしないと
845: 2020/05/10(日)13:27 ID:EdgxbLB4(2/2) AAS
>>843
>>844
あ……すみません。
コンストラクタの綴り治せばエラー取れました(汗
ご教授ありがとうございました
846(1): 2020/05/10(日)17:58 ID:Pcmn53iK(1) AAS
namespace std { inline namespace tr1 {} }
#include <memory>
847(1): 2020/05/10(日)18:02 ID:LV0wbaaG(1/2) AAS
std名前空間に何かするのは基本的に未定義動作に繋がるのでやめようね
848(1): 2020/05/10(日)18:15 ID:3khm8gAC(1) AAS
カラオケで自分が歌いながら録音したカセットテープを爆音でドライブしながら女に聞かすようなものだな
これどう?オレが歌ってんだけど?的な
849: 2020/05/10(日)18:53 ID:0gvZuU03(1) AAS
>>848
それ良くやる
850: 2020/05/10(日)19:05 ID:m91+LxrO(1) AAS
女「さむっ・・・オープンカーかと思ったわ」
851(2): 2020/05/10(日)19:30 ID:657zsB50(1) AAS
>>846
どうもです、しかし自分の環境だとうまくいかないですね。gcc 5.4.0 です。
error: ‘shared_ptr’ is not a member of ‘std::tr1’
std::tr1::shared_ptr<Hoge> hoge;
^
とりあえず>>840を試してみたんですが、やってみるとインクルードファイルが意外と多く、そのほとんどに
#include <tr1/なんちゃら> があり、これらを全て tr1無しにする必要が。
コンパイラーのフラグ等でtr1無しをインクルードするようなことってできましたっけ? うわーさらに脇道。
とりあえず上記を書き直すとした場合、変更量が増えるにつれ、やっぱ全部のファイルで素直にtr1を
全部置換したほうがいいんじゃないかという気が徐々に... っておい > 自分
>>847
御意。ちなみにstdは普通の名前空間とは違うということですか?
しかし namespace の使い方の勉強になりました。いやあ色々思い付かれてすごいです。
852: 2020/05/10(日)19:41 ID:5OK5MvZd(2/2) AAS
>>851
#include <tr1/〜> も保持するなら、自分のソースツリーに tr1/〜 を捏造して
その中に #include <〜> と >>840 を並べて書けばいいでしょ。
まぁ置換で済むならそっちだろうけど。
853: 2020/05/10(日)21:40 ID:LV0wbaaG(2/2) AAS
>>851
std名前空間の中は標準とその実装のための特別な場所
外部リンク:ja.cppreference.com
854: 2020/05/11(月)06:44 ID:WjiQACf7(1/2) AAS
使われないけど標準なんです。
855(4): 2020/05/11(月)10:06 ID:ihiMo4aq(1/3) AAS
関数内で宣言した変数を途中でconst化したいときってどうやったらいいですか?
関数というのはこんな感じです
void func() {
int a;
〜aの値を設定する百行くらいの処理〜
〜aを用いたメイン処理。途中で誤ってaを変更しないようにしたい〜
}
aをconstで宣言しておいてaを設定するところはconst_castするというのはやりたくないです。
初期化用関数initializeを作って const int a = initialize(〜); とするしか方法はないですか?
できればそれもしたくないのですが
856: 2020/05/11(月)10:09 ID:MhpqGE2N(1) AAS
&a にアクセスする権限を readonly にするとか
環境依存だろうけど
857(1): 2020/05/11(月)10:13 ID:vLTbwMZ+(1/2) AAS
>>855
a に設定する値を求める処理を関数化して、その戻り値でconstのaを初期化する。
858: 2020/05/11(月)10:14 ID:vLTbwMZ+(2/2) AAS
あ、したくないって書いてあったね
859(1): 2020/05/11(月)10:18 ID:m+8/4tPw(1) AAS
>>855
初期化用関数を作るのが嫌な理由は何?
外のスコープに名前を付けて置くのが嫌ということならラムダ式で済むと思うんだけど。
860(3): 2020/05/11(月)10:53 ID:ihiMo4aq(2/3) AAS
>>857>>859
関数作るのが嫌なのは、気分ですね。バカバカしい理由ですみません。
関数外に置くのが嫌でラムダ式は多用しているのですが、使うときはある程度まとまった処理をするときなので
初期化程度のことにラムダ式を持ち出すのは大仰な気がしてやりたくありません。
これまた個人的な好みで恐縮ですが。
(ちなみに>>855で挙げた初期化処理が百行くらいというのは大げさで、概ね数行くらいです。)
861: 2020/05/11(月)11:22 ID:rmb+jfMY(1/6) AAS
どうしてもなら、こうだな
int a_;
//a_で初期化処理をする
int const& a = a_;
//aはconst
862: 2020/05/11(月)11:26 ID:rmb+jfMY(2/6) AAS
アホらしいけど、こんな手も考えられる
struct sample
{
int a;
void func() {
//初期化処理
std::as_const(*this).func();
}
void func() const {
//aをconst扱い
}
};
863: 2020/05/11(月)11:30 ID:tShYcoYg(1) AAS
後半をlambda化すれば
aをコピーキャプチャしてmutableにしなければconstになる
864(1): はちみつ餃子 ◆8X2XSCHEME 2020/05/11(月)11:37 ID:pGzfxkdL(1) AAS
GCC や Clang の拡張を使ってよいならこういう書き方は出来る。
void func() {
const int a = ({int a; a=1; a;}); // ブロック内で初期化処理を書いて値を返す
std::cout << a << std::endl; // メイン処理
}
たぶん >>855 が考えている用途だとこれが一番楽なんじゃなかろうかと思うんだけど、
標準ではないってのはやっぱりネックになってくるな。
865: 2020/05/11(月)11:54 ID:WjiQACf7(2/2) AAS
constウイルスw
866(1): 2020/05/11(月)12:17 ID:oXH9qZIA(1) AAS
ポインタ使えばいいのに
const付きのポインタを宣言だけしといて初期化のスコープ内でアドレス渡せばいい
867: 2020/05/11(月)12:21 ID:vUv7mwxB(1) AAS
>>860
RAII教に入信しておとなしく初期化ラムダ関数を使うがよい
868: 2020/05/11(月)14:54 ID:NX9zuntd(1/2) AAS
IT掲示板群 外部リンク[aspx]:x0000.net
学術の巨大掲示板群 - アルファ・ラボ 外部リンク:x0000.net
数学 物理学 化学 生物学 天文学 地理地学
IT 電子 工学 言語学 国語 方言 など
simulationライブラリで純粋な関数式プログラミングをする
外部リンク[aspx]:x0000.net
UIライブラリ (C#, 2D) を作ったよ
外部リンク[aspx]:x0000.net
連続と離散を統一した!
外部リンク[aspx]:x0000.net
4Dエンジン
外部リンク[aspx]:x0000.net
matrixのライブラリ
外部リンク[aspx]:x0000.net
ある強力なFor関数
外部リンク[aspx]:x0000.net
SQLライブラリ
外部リンク[aspx]:x0000.net
869: 2020/05/11(月)14:54 ID:NX9zuntd(2/2) AAS
IT掲示板群 外部リンク[aspx]:x0000.net
学術の巨大掲示板群 - アルファ・ラボ 外部リンク:x0000.net
数学 物理学 化学 生物学 天文学 地理地学
IT 電子 工学 言語学 国語 方言 など
simulationライブラリで純粋な関数式プログラミングをする
外部リンク[aspx]:x0000.net
UIライブラリ (C#, 2D) を作ったよ
外部リンク[aspx]:x0000.net
連続と離散を統一した!
外部リンク[aspx]:x0000.net
4Dエンジン
外部リンク[aspx]:x0000.net
matrixのライブラリ
外部リンク[aspx]:x0000.net
ある強力なFor関数
外部リンク[aspx]:x0000.net
SQLライブラリ
外部リンク[aspx]:x0000.net
870: 2020/05/11(月)14:58 ID:vIusnhzf(1/2) AAS
>>866
なるほど、考えてみれば参照型にすればいいんだ。
int a;
(a に対する初期化処理);
const int &a2 = a;
(a2 を読み取るだけの処理);
871(1): 2020/05/11(月)15:01 ID:vIusnhzf(2/2) AAS
変数名として灰化の用にすればわかりやすいかもしれない。
物理学では、a0 は、a の初期値を意味することが多いので、学術的にも分かり易い。
int a0;
(a0 に対する初期化処理);
const int &a = a0;
(a を読み取るだけの処理);
872: 2020/05/11(月)15:02 ID:rdm6Cg4w(1/4) AAS
>>871
誤: 変数名として灰化の用にすればわかりやすいかもしれない。
正: 変数名としては、以下のようにすれば分かり易いかも知れない。
873(2): 2020/05/11(月)15:28 ID:ZT/W926b(1) AAS
a0がスコープから消えないのは片手落ち
どのみちトリッキーなことして読み手を混乱させることしない方がいい
単純にスコープを一画面に収まるぐらいに短くしろ
874: 2020/05/11(月)15:33 ID:rmb+jfMY(3/6) AAS
キモい個人サイトの宣伝をNG登録っと
875: 2020/05/11(月)16:16 ID:rdm6Cg4w(2/4) AAS
>>873
>a0がスコープから消えないのは片手落ち
言われてみれば。
876(2): 2020/05/11(月)16:35 ID:gZOsi0FN(1) AAS
処理を途中で止めて、変数とかvectorの中身を確認したりするソフト知らない?
877: 2020/05/11(月)16:37 ID:rdm6Cg4w(3/4) AAS
>>873
以下のようにすればその問題も一応は解決する。
int a;
(a に対する初期化処理);
{
const int &a0 = a;
const int &a = a0; // 外の a とは別の a を宣言。
(a を読み取るだけの処理);
}
さらに
#define XXX(_x_) const int &_x_##0 = _x_; const int &_x_ = _x_##0
というマクロを導入すれば、
int a;
(a に対する初期化処理);
{
XXX(a);
(a を読み取るだけの処理);
}
でいける。
878: 2020/05/11(月)16:38 ID:rdm6Cg4w(4/4) AAS
>>876
それがデバッガー。
IDEの中に入ってる。
879: 2020/05/11(月)16:59 ID:rmb+jfMY(4/6) AAS
>>876
Visual Studioに標準で入ってるよ
880: 2020/05/11(月)17:54 ID:ihiMo4aq(3/3) AAS
やはり大人しく初期化関数使います
いろいろとアドバイスありがとうございました
881(1): 2020/05/11(月)18:09 ID:UkUll7O4(1/6) AAS
幅優先探索において座標によって侵入コストが均一でない場合に対応するためにプライオリティキューを用いて、
スタート地点からの総移動コスト値(int)を格納する2次元配列と、
それに対応するインデックスとなる座標を格納する構造体(POINT)で実装したいのですが、
ProgrammingPlacePlusというサイトのC++編の「標準ライブラリ」の第12章(priority_queue)のサンプルコードに習って、
使用コンテナがvectorの場合はうまくいくのですが、listにするとコンパイルエラーになってしまいます
int move_cost[256][256];
bool operator >( POINT a, POINT b )
{
return ( move_cost[a.y][a.x] > move_cost[b.y][b.x] );
}
//vector版
std::priority_queue< POINT, std::vector<POINT std::greater<POINT> > vector_prio_que;
//list版
std::priority_queue< POINT, std::list<POINT std::greater<POINT> > list_prio_que;
初心者ですみません
どうすればlistでも動作させられるのかご教示頂けませんでしょうか
882: 2020/05/11(月)18:20 ID:rmb+jfMY(5/6) AAS
>>881
vectorならokでlistはngというと、イテレータの種類じゃね?
vectorはランダムアクセス、listはバイディレクショナルという違いがあって
よく引っかかる要注意箇所だよ
883(2): 2020/05/11(月)19:14 ID:UkUll7O4(2/6) AAS
priority_queueの内部使用コンテナとしては、vector、list、dequeは条件を満たしていると書いてあったので、できるはずだと思ったのですが…
priority_queueは、topメンバ関数で最も優先度の高い要素にしかアクセスできず、
自分で書いたソースでは添え字やイテレータによる直接のアクセスは行っていない
(メンバ関数も、.push .pop .top .emptyしか呼び出していない)のですが、
コンパイルエラーの表示では、ご指摘のとおりリバースイテレータがどうのと出ていました
error C2784: 'reverse_iterator<_RanIt>::difference_type std::operator -(const std::reverse_iterator<_RanIt> &,const std::reverse_iterator<_RanIt2> &)'
:テンプレート引数を 'const std::reverse_iterator<_RanIt> &'に対して 'std::list<_Ty>::_Iterator<_Secure_validation>' から減少できませんでした
'std::operator -' の宣言を確認してください。
これは内部的にイテレータの操作がされておりそこでエラーになっている感じなのでしょうか?
algorithmやxutilityの該当箇所を見ても難しすぎてわかりませんorz
884(1): ◆QZaw55cn4c 2020/05/11(月)19:16 ID:X9lKtqAV(1) AAS
>>864
例の奴ですね、ならば、ここはラムダ式の出番でしょう、ラムダ式を定義して即評価します
const int a = [](){int a; a = 1; return a; }();
私以外にもこういうのを希望する人がいるということで、安心しました
885: 2020/05/11(月)19:28 ID:VXScjWrk(1/2) AAS
> priority_queueの内部使用コンテナとしては、vector、list、dequeは条件を満たしていると書いてあったので
それってどこ情報?
軽くググった限りだと、vector、dequeしか出てこないけど
886(1): 2020/05/11(月)19:48 ID:UkUll7O4(3/6) AAS
Programming Place Plus というサイトで配布されていた オフライン版(2019-07-01更新版)の C++編の「標準ライブラリ」の第12章(priority_queue)に書いてありました
887: 2020/05/11(月)20:14 ID:1e8qKpQP(1/2) AAS
リファレンスにはvectorとdequeしかないね
外部リンク:ja.cppreference.com
外部リンク[html]:cpprefjp.github.io
888: 2020/05/11(月)20:21 ID:UkUll7O4(4/6) AAS
vectorの部分をdequeに替えたら問題なく動作したので、対応してるのvectorとdequeだけの可能性高そう
できゅーならできる、なんちゃって
889: 2020/05/11(月)20:42 ID:LZ5jZAGa(1) AAS
(デックなんだけど楽しそうだから黙っとこう…)
890: 2020/05/11(月)20:48 ID:oppF2e3I(1) AAS
>>886
そのサイトが取り違えている
外部リンク[html]:cpprefjp.github.io
>要件を満たすものとしては deque と list
queue | Programming Place Plus C++編【標準ライブラリ】 第11章
外部リンク[html]:programming-place.net
>Container には、vector(第5章) や list(第6章)
***
外部リンク[html]:cpprefjp.github.io
>要件を満たすものとしてはvectorとdeque
priority_queue | Programming Place Plus C++編【標準ライブラリ】 第12章
外部リンク[html]:programming-place.net
>Container には、deque(第7章) や list(第6章)
891: 2020/05/11(月)21:01 ID:UkUll7O4(5/6) AAS
そこのサイト詳しくわかりやすく解説してくれているから頼りにしていたのですけど、間違いがあるとは残念ですね…
vectorは要素をずらしたりコピーしたりで実行速度が遅そうだと思ってlistを使いたかったのですが、
素人考えでしたかね
892: 2020/05/11(月)21:10 ID:1x7ET1G/(1) AAS
dequeでよくね
893: 2020/05/11(月)21:30 ID:rmb+jfMY(6/6) AAS
>>883
difference_typeって書いてあんじゃねえかよ
バイディレクショナルなイテレータは引けねえんだよ
つまりlistは使えねえってこと
894: 2020/05/11(月)21:33 ID:M5DpbX0A(1/2) AAS
>>883
std::priority_queue
外部リンク[html]:cpprefjp.github.io
ここには、vector・dequeがあると書いてある。
list は書いていない
895: 2020/05/11(月)21:37 ID:VXScjWrk(2/2) AAS
priority_queueって内部実装がヒープみたいだから、
末尾にしか追加削除しないと思われるので、vectorで十分では
896: 2020/05/11(月)21:45 ID:1e8qKpQP(2/2) AAS
コンセプトがくればこういう悲しい出来事も減るのかな
897: 2020/05/11(月)21:47 ID:zAHWYKkR(1) AAS
C++って何作れば勉強になるんだろ
898: 2020/05/11(月)21:54 ID:UkUll7O4(6/6) AAS
縦10マス×横40マスの地図で幅優先探索を100回まわして時間計ったら、
vectorだと989ms
dequeだと904ms
で大差ないかんじでした
デフォルトのままvectorを利用していきたいと思います
アドバイス下さいました熟練者の皆さまありがとうございましたm(_ _)m
899(2): 2020/05/11(月)22:38 ID:M5DpbX0A(2/2) AAS
漏れは、2分ヒープを自分で作って、ソートしたりしたけど、
配列の[0]は使わず、[1]から始めると計算が楽なので、
親1, 左右の子は2, 3で、法則は親n, 子2n, 2n+1
コンテナの最後にオブジェクトを追加し、
それが親の数値より小さい場合は、
再帰的に親と交換していく (親子を交換)
再帰的に、親は両方の子以下の数値をもつ。
左右の子(兄弟)の大小関係は考慮しない
配列の先頭要素[1]をPopし、配列の最後の要素を、
[1]に持ってきて、そこから再帰的に、左右の子と比べながら、
子の数値より大きい場合は、入れ替える
ピッコロ大魔王は、これよりもさらに効率的な方法を言ってたけど
このアルゴリズムでは、deque のリンクは不要だろ?
親n, 子2n, 2n+1 で、メモリの場所が分かるのでは?
900(1): はちみつ餃子 ◆8X2XSCHEME 2020/05/12(火)00:41 ID:NsC/lgb+(1/4) AAS
>>884
質問者はこの場面でラムダ式を持ち出したくないと >>860 に書いてある。
どうして文脈を読めんのだ。
901: 2020/05/12(火)01:32 ID:nCmEHjd6(1) AAS
>>899
なるほど、n, 2n, 2n+1 番の要素に格納してゆくかんじですか、素晴らしいアイデアですね
自力での実装がどうしても必要になったら、配列で作るときのヒントにさせていただきますね
>vectorだと989ms
探索1回あたり10msもかかるのはちょっとおかしいだろうと思って見直したら、
ソリューション構成をDebugにして、「デバッグ開始」してるせいでした
ソリューション構成をReleaseにして、「デバッグなしで開始」にしたら、
探索1回あたり0.02ms弱に収まりました(vector使用時)
STLコンテナ使っててデバッグモードだと500倍も遅くなりうるのか…
ちなみにdeque使用時は0.05msでやや遅めだったのでやはりvectorを使う方がよさそう
902: 899 2020/05/12(火)02:06 ID:q3FkXSvr(1) AAS
普通の実装では、[0]から始めると、
親0, 左右の子は1, 2で、親1, 左右の子は3, 4で、
親n, 子2n+1, 2n+2、となり複雑
子3なら親は、(3-1)/2 = 1
子4なら親は、(4-1)/2 = 1.5 で、切り捨てて1
>>899
では、配列の[0]は使わない。[1]から始めると計算が楽
親1, 左右の子は2, 3で、親n, 子2n, 2n+1
子2なら親は、2/2 = 1
子3なら親は、3/2 = 1.5 で、切り捨てて1
903: 2020/05/12(火)09:47 ID:9iboxsgQ(1) AAS
呼び出し履歴で過去の状態に戻れるのは、記録してるからだし。
904: 2020/05/12(火)11:15 ID:4WwqN1hQ(1) AAS
dequeue一択
905: 2020/05/12(火)11:26 ID:xLvzOPR4(1) AAS
そういえばdeque使ってよかったって経験ないなぁ
906: 2020/05/12(火)11:33 ID:8l4UOEBM(1/2) AAS
heap構造ならvectorが速いよね
事前に適切なサイズでreserveしておけば再配置も起きないし
907: 2020/05/12(火)11:52 ID:Jgs88fl2(1/3) AAS
前後にニョキニョキ伸ばすような用途だとdequeが一番よ
908(1): 2020/05/12(火)12:41 ID:ph0RCKO5(1/2) AAS
複数のソース・ヘッダーファイルのセットから一つの動的dllは作れないのでしょうか?
909(1): はちみつ餃子 ◆8X2XSCHEME 2020/05/12(火)12:45 ID:NsC/lgb+(2/4) AAS
>>908
作れるよ。
910(1): 2020/05/12(火)13:34 ID:ph0RCKO5(2/2) AAS
>>909
ありがとん
1つのソース・ヘッダーのセットから1つのdllを作るのには成功したのですが、解説サイトも見つからず困っています
911: はちみつ餃子 ◆8X2XSCHEME 2020/05/12(火)13:43 ID:NsC/lgb+(3/4) AAS
>>910
ツールチェインによって手順は違うけど、
ソースファイルがひとつであろうが複数であろうが特別に違うことはしないと思うんだけど。
912(1): 2020/05/12(火)14:09 ID:j/0vQ47K(1/2) AAS
何が困っているのかさっぱりだぜ
リンカでdllにするんだろ
複数のオブジェクトファイルをリンクすることになんの疑問が
913: 2020/05/12(火)14:15 ID:9Z5koysX(1/4) AAS
BASICとかやってた部類の人間だとリンクの概念とかわからんかもね
914: 2020/05/12(火)14:17 ID:9Z5koysX(2/4) AAS
そういう化石の人がつい最近いじりはじめた可能性もある
915: はちみつ餃子 ◆8X2XSCHEME 2020/05/12(火)14:18 ID:NsC/lgb+(4/4) AAS
コマンドラインから使うときでもだいたいコンパイラドライバが
いい感じにやってくれるから細かなことまで意識する機会も
あまり無いしな。
916: 2020/05/12(火)14:24 ID:9Z5koysX(3/4) AAS
昔は依存関係調べるメイクファイルビルダーみたいなの使ってたけど
今はそこら辺もコンパイラが全自動で全部やってくれる
917: 2020/05/12(火)14:24 ID:s06VnCgE(1) AAS
なんかデジャブ…
つい数日前にもまとめてlib化はできるけどdll化できないって質問があったような…
918: 2020/05/12(火)14:24 ID:SVn+5d28(1) AAS
>>912
おそらく本人は何も分かっていない、何が分かっていないか分からない、書いてあったことを真似るしか出来ない、ということなんだと思う。
919: 2020/05/12(火)14:30 ID:9Z5koysX(4/4) AAS
写経から悟りを得るかどうかの瀬戸際という辺りか
920: 2020/05/12(火)14:32 ID:0QBBSU9v(1) AAS
40年前の子供向けBASIC雑誌ですら動的生成を当たり前のようにしてたのになに言ってんだか
C++は何十年遅れてるのってレベル。ゲイツ舐めすぎ。おまえらはジョブス以下。
921: 2020/05/12(火)15:24 ID:j/0vQ47K(2/2) AAS
プログラムからコンパイラ呼び出して動的ライブラリ作って呼び出せばいいじゃん
922: ◆QZaw55cn4c 2020/05/12(火)18:31 ID:cMBaML9B(1/2) AAS
>>900
初期化時に別に関数やメンバ関数(メソッド)を立てたくない、という >>860 の要望は、かつて私も体感した感覚であり共感を覚えましたので、失礼だとは思いましたが背中を押す意味もこめて敢えてラムダ式を推すことにいたしました
923: 2020/05/12(火)19:33 ID:zY2j7Z+k(1) AAS
MacだとCMakeが便利だった。
924(1): 2020/05/12(火)19:38 ID:HKiNDHJQ(1/2) AAS
即時実行されるlambdaなんて
文法上殆んどblock変わらん見た目で、
最適化かければ性能上もblockと変わらんだろ
[&]{
}();
925(1): 2020/05/12(火)19:48 ID:Jgs88fl2(2/3) AAS
即実行ラムダのインライン展開って本当にやってくれるの?
もちろんプログラマとしては期待するところだけど本当に主要コンパイラがやってるか誰か検証してる?
926: 2020/05/12(火)20:13 ID:Qfzty+97(1) AAS
一回しか呼ばれないんならインラインも糞も無い罠
927: 2020/05/12(火)20:26 ID:HKiNDHJQ(2/2) AAS
>>925
そんなのアセンブリ出力するかobjdumpすりゃ確認できるだろ
msvcですらやっているよ
928: 2020/05/12(火)20:28 ID:u3gpKmNT(1/3) AAS
普通の関数コールだって呼び元が1箇所ならインライン展開する
929: 2020/05/12(火)20:38 ID:Jgs88fl2(3/3) AAS
そっかMSVCがやってるなら当然みんなやってるわな
サンクス
930: 2020/05/12(火)20:38 ID:u3gpKmNT(2/3) AAS
いやそんな事もないけど
931: ◆QZaw55cn4c 2020/05/12(火)20:40 ID:cMBaML9B(2/2) AAS
>>924
式しかかけない場所というのがあって、そういう場所では文では駄目ですね
932: 2020/05/12(火)21:12 ID:sL+fzMl7(1/2) AAS
set::insert()で警告が出るんですが、なんででしょう?vc2015です。
std::set<int> items;
items.insert(1); // ここで警告 C4800
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include\utility(175): warning C4800: 'int': ブール値を 'true' または 'false' に強制的に設定します
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include\xtree(1823): note: コンパイル対象の関数 テンプレート インスタンス化 'std::pair<std::_Tree_const_iterator<・・・
933(1): 2020/05/12(火)21:13 ID:u3gpKmNT(3/3) AAS
書いてある通りじゃね?
934(1): 2020/05/12(火)22:10 ID:sL+fzMl7(2/2) AAS
>>933
メッセージ内容見ても全然意味がわからないです・・・
警告出ないようにするには、どう修正したらいいですか?
#pragma warning とかでなくて
935: 2020/05/12(火)22:13 ID:8l4UOEBM(2/2) AAS
コンパイラを代える
上下前次1-新書関写板覧索設栞歴
スレ情報 赤レス抽出 画像レス抽出 歴の未読スレ AAサムネイル
ぬこの手 ぬこTOP 0.349s*