[過去ログ] C++相談室 part156 (1002レス)
1-

このスレッドは過去ログ倉庫に格納されています。
次スレ検索 歴削→次スレ 栞削→次スレ 過去ログメニュー
623
(7): 2021/07/04(日)03:21 ID:WJcubPcO(1/13) AAS
auto hoge = func()
は場合によってはコピーが起きる
という印象、

なぜなら戻り値をスタックのどこに積むかをfunc()の側で指定できないから
hogeの実体ドンピシャにfunc()内で構築できる保証が無い
コピーが省略され得るのは
 auto hoge = func();
 bar(hoge);
みたいな呼び出し元がhogeの用の一時的領域を次の関数呼び出しの引数としてやりくりできる場合だけなんじゃないの
624: 2021/07/04(日)07:20 ID:kv3QS/1l(1) AAS
ISO/IEC 14882に準じて
おぺれーたーらいとしふと
625: 2021/07/04(日)08:34 ID:mLloSLib(1/2) AAS
>>623
???
最適化されて bar(func()) になるときだけオブジェクトの構築が省略されるって言いたいの?
アホか全然レイヤの違う話だよ
右辺値左辺値の概念全く理解しとらんのか (何十年前のプログラマだ)
「印象」でものを語るな
626: 2021/07/04(日)10:01 ID:mLloSLib(2/2) AAS
それはそうと、こんなスレでも右辺値と左辺値よくわかってない (概念としてはわかっててもある場合のある値がどっちか判然としない) 人が多いのは、C++のムーブセマンティクスが洗練されてる証拠かもな
つまり、プログラマの預かり知らぬところで自動でコピーとムーブが仕分けされているという
627
(6): 2021/07/04(日)10:11 ID:dMFRzHLQ(1/6) AAS
>>623
外部リンク:wandbox.org
そんなことないよな? と思いつつやってみた
まあ、そんなことないよな

ただ実験してて一個だけ気になったのが
take_S(S());
ってやった場合、default→moveじゃなくて単にmoveとしか表示されなかった
C++11/14でも-fno-elide-constructorsを付けない限りmoveだけ
これってなんで?
628: 2021/07/04(日)10:44 ID:pili1Lz/(1) AAS
>>619
万葉集は読み下しですらないからな
629
(1): 2021/07/04(日)11:45 ID:WJcubPcO(2/13) AAS
>>627
解説キボティーヌ
"copy"と表示されているわけだが
630: 2021/07/04(日)11:56 ID:WJcubPcO(3/13) AAS
つかそれを除けば>>623の通りなんじゃないの

>take_S(S());
>ってやった場合、default→moveじゃなくて単にmoveとしか表示されなかった
これは呼び出し元がS()の戻り値の実体をtake_S()の引数の実体と合一(スタック上の同一アドレス)にできた例
defaultコンが呼ばれなかったのはstruct Sがメンバを持たないから最適化でデフォルトコンストラが削除された例

通常の関数呼び出しでcoutする処理が削除されたらそればバグだが、
コンストラクタの呼び出し削減の最適化はコンストラクタ内で副作用のある処理を行っている可能性を
無視して行われることが規格のどっかで認められているはず……
631
(1): 2021/07/04(日)12:12 ID:WJcubPcO(4/13) AAS
>最適化されて bar(func()) になるときだけオブジェクトの構築が省略されるって言いたいの?
微妙にちげう func()がオブジェクトをコピー返しする関数である以上、その場合だけムーブにする余地があると言ってゐる
実際は
 auto hoge = func()
 bar(hoge)
 (この後hogeを使う人は居ない)
と分けて書いたら"move"になりそうなケースなのに"copy"になったらしいが(>>627のリンク先

>アホか全然レイヤの違う話だよ
ムーブにできるのは参照の付け替えとみなせるケースなので上の話(コピーをムーブと読み替え得る条件)が別レイヤの話とは認められない
632
(1): 2021/07/04(日)12:32 ID:dMFRzHLQ(2/6) AAS
>>629
表示されたってことは省略されてないよね?
633: 2021/07/04(日)12:34 ID:dMFRzHLQ(3/6) AAS
実験の部分を同時に話題にするべきではなかったな
634
(1): 2021/07/04(日)12:54 ID:WJcubPcO(5/13) AAS
>>632
"move"にならずに"copy"になったのは謎だと>>631に書いてある

とわいえ、>>623の主張を整理すると、
 (1) func()が定義上オブジェクトをコピー返しする関数である場合、auto hoge = func() がムーブになるとは限らず、場合によってはコピーが起きる
 (2) ただし、bar(func()) というケースでは、func()の戻り値をbar()に渡す際に、コピーではなくムーブが選択される余地がある
というものであって、bar(func())に類似のケース(>>627のリンク先)でムーブにならずコピーになったからといって>>623が否定されたことにはならない
(∵ムーブが選択される「余地がある」と言っただけであってムーブにする義務があると言ったわけではない
635: 2021/07/04(日)13:00 ID:WJcubPcO(6/13) AAS
ここで「func()が定義上オブジェクトをコピー返しする関数である」のに何でコピーが削除されてムーブに成り得るのか?
という疑問を抱く向きもあるかもしれないが、
これについては構造体やオブジェクトをコピー返しするような関数func()が実際には
return valueの置き場所にデフォルト構築するだけのコードに落ちることがあるのを見たらワカル
636
(1): 2021/07/04(日)13:13 ID:dMFRzHLQ(4/6) AAS
>>634
もしかして、コピーの代わりにムーブでオブジェクトが構築されることを「コピー省略」だと思ってる?だとしたら違うよ

ていうか実験の部分は自己解決しました
C++17で必須になったっていうだけで、それまでも(C++98ですらも)省略されることが許されるというのは明記されていたんですね
637: 2021/07/04(日)13:25 ID:bouvqZmG(1/3) AAS
「コピー返し」ってなんぞ?
638
(1): 2021/07/04(日)13:29 ID:WJcubPcO(7/13) AAS
>>636
>もしかして、コピーの代わりにムーブでオブジェクトが構築されることを「コピー省略」だと思ってる?だとしたら違うよ
別に

言っているのは
1. オブジェクトの構築はfunc()内のどこかしらで行われる
2. 1の方法によっては、func()がreturn valueをreturnする際のコピーは省略される(func()がそういうコードになる
3. func()がスタック上に返したreturn valueを呼び出し元が自動変数hogeのエリアにコピーする代わりにbar()の引数エリアにmoveする
 ことがある(>>601が言うように常にmoveになる、というわけではない
と言う簡単な主張
639
(1): 2021/07/04(日)13:49 ID:dMFRzHLQ(5/6) AAS
>>638
じゃあ結局>>623のこの部分は間違いってことでいいの?

> コピーが省略され得るのは
>  auto hoge = func();
>  bar(hoge);
> みたいな呼び出し元がhogeの用の一時的領域を次の関数呼び出しの引数としてやりくりできる場合だけなんじゃないの
640
(1): 2021/07/04(日)14:05 ID:bouvqZmG(2/3) AAS
意味ワカンネ

1. func が内部でオブジェクトを構築する話
2. func の返り値を変数 hoge に束縛する話
3. func の返り値を後で他の関数に渡す話

全部切り分けて考えろよとしか思えんのだが

そして 2 について言えば>>621に尽きるだろとしか思えんのだが
641
(1): 2021/07/04(日)14:15 ID:WJcubPcO(8/13) AAS
>>640
いやすまん2は確かに間違いでauto hoge = func()はhogeへのmoveで済む

>>639
いやすまん「〜できる場合だけ」という限定は間違いやった

ついでに言うとbar(func())でたまたまfunc()がスタック上に作ったreturn valueのアドレスも変えずにそのままbar()に渡せるとき
moveが起きるという主張も間違いだったかも……(アドレスも変わらないのなら何の構築も不要
642
(4): 2021/07/04(日)14:27 ID:bouvqZmG(3/3) AAS
何もかもおかしいよお前
「コピー返し」って結局なんやねん
独特の語法でわけのわからんことを主張するな
「印象」「かもしれない」で物事を主張するな
何がわかってて何がわかってないか知れ
質問と主張をごちゃまぜにするな
本格的に社会に居場所なくなるぞ

「全部取り下げます」とだけ言って去れ
で一から勉強しろ
643
(1): 2021/07/04(日)14:32 ID:2p3tbjy0(1) AAS
RPGでアイテムを移動させた時に間違ってコピーされてアイテムが増殖する
ムーブしないといけない
アイテムは一個だけ
644: 2021/07/04(日)14:37 ID:HHbHqtlq(1) AAS
>>642
面倒見よくて草
昔はこの板にもアンタみたいな厳しい先輩いっぱい居たのにな
今はニワカと趣味グラマが何周送れかわからんポエム呟きあってるだけだし
昔からいる人らは完全スルーしてるはず
645
(1): 2021/07/04(日)14:52 ID:WJcubPcO(9/13) AAS
>>642
Callerが(スタック上に)確保したメモリに対してcalleeが構造体を返すという返し方の意味
これについては統一した用語が無いようなのでむしろ知りたいっすね……

>>643
>>623のコードでSにムーブコンが定義されていなかったら増殖を意図しないケースでも
コピコンが呼ばれるのだから>>643はたとえとしてはイマイチ
646
(3): はちみつ餃子 ◆8X2XSCHEME 2021/07/04(日)15:12 ID:7/Zaj2J4(1) AAS
>>645
要件を満たすとき (返却値が prvalue のとき) は変数の場所に直接にオブジェクトが構築される.。
コピーやムーブを省略できるというのはそういう意味で、
特に C++17 以降ではコピー省略が許されるときにはコピーコンストラクタもムーブコンストラクタも存在しなくてもいい。

外部リンク:wandbox.org
647
(1): 2021/07/04(日)15:50 ID:WJcubPcO(10/13) AAS
>>646のコードをVS2019でビルドしたら
>error C2280: 'foo::foo(foo &&)': 削除された関数を参照しようとしています
と言われるorz

ていうか「prvalueならば必ず変数の場所に直接にオブジェクトが構築される」(例外なくそうなる)のだとしたら
これはcallerがcalleeに構築すべき変数のアドレスを渡さねば実現できない芸当だけど
ABIにそんな隠れた第n引数を設けることまでC++の規格で決めちゃって委員会、
とそこはかとなく疑問が……
(funcがメンバ変数だった場合、隠れた第1引数でthisを渡すことになっているのにこれにさらに追加?
648
(1): 2021/07/04(日)15:56 ID:xLbwwiyt(1) AAS
いいからお前はRVOでぐぐって来い
話はそれからだ
649
(1): 2021/07/04(日)16:02 ID:WJcubPcO(11/13) AAS
>>648
これか
外部リンク:blog.kmc.gr.jp
>まるでメンバ関数における暗黙のthisポインタのように、関数の引数に戻り値を格納する先の変数へのアドレスを渡します。
>そしてそのアドレスの先の上にオブジェクトを構築することで、関数内部での一時オブジェクト
>生成を呼び出し元のオブジェクト生成とみなすことができます。 このようにしてRVOは実現されています。

>まるでメンバ関数における暗黙のthisポインタのように、関数の引数に戻り値を格納する先の変数へのアドレスを渡します。
mjk、
650: 2021/07/04(日)16:18 ID:2qJME2iB(1) AAS
>>649
RVO は、最適化の一種なので、実現方法は色々。
とにかく、コンパイラが、関数の戻り値から左辺へのコピーやムーブを
なるべく減らして、いきなりダイレクトに左辺に書き込むような方法を探し出して
コード化する。
それをどやってやるかは、関数呼び出しの ABI 依存。
651
(1): 2021/07/04(日)16:52 ID:VOtERW9V(1) AAS
>>647
エラーになるのは、VS2019のデフォルトがC++14だから。
プロジェクトのプロパティ→構成プロパティ→C/C++→言語 の
「C++言語標準」を「ISO C++17標準(/std:c++17)」に変更すれば通る。
652
(1): 2021/07/04(日)18:28 ID:WJcubPcO(12/13) AAS
>>651
確かに「C++言語標準」を「ISO C++17標準(/std:c++17)」に変更したら通った

>>651
>(RVOを)どやってやるかは、関数呼び出しの ABI 依存。
そういうものだと今の今まで思っていたが、
C++17で>>646のコード(コピコンもムーブコンも明示的に削除)がビルドが通るようになるということは、
第2の隠れた引数でcallerがcalleeに構築すべき変数のアドレスを渡すことが
C++17では義務化されるとしか解釈できないのでは……
653
(3): 2021/07/04(日)20:21 ID:WJcubPcO(13/13) AAS
第2の隠れた引数でcallerがcalleeに構築すべき変数のアドレスを渡しているのだとすると
>>627のコードが"default"の次に"copy"になるのはある程度説明がつく
 1. return_S()関数でS構築 --- ここでS:S()が呼ばれ、"default"表示
 2. auto hoge = return_S()では何も起きない(∵1で&hogeにSが構築済み)
 3. take_S(hoge)で呼び出しの引数としてhogeをコピー
   --- &hogeにあるSが、スタックの上の方に引数としてコピーされる結果"copy"表示

しかしhogeはその後使っていないのだから、コンパイラ的には3はmoveになる余地があるはず

なお>>641までの漏れのレスは第2の隠れた引数は仮定せず、return_S()(callee)がスタックのトップに
return valueとしてS()を構築して、
それが呼び出し元(caller)が&hogeにcopy(ムーブコンがあればmove)する穏当なモデルを考えていた
省2
654: 2021/07/04(日)22:02 ID:dMFRzHLQ(6/6) AAS
>>652
別に実装として「隠れた引数」を使えとは規格上決まっていないよ
処理系は適当な専用のグローバル変数を使うようなコードを出力しても構わない

>>653
なんで>>642が怒り狂うのか?
>>642を読んで分からない分からない?
あなたの一連のレスはあなた自身以外の誰のためにもなっていないんだよね
>>642でするな、って言われていることは、そういう自分のためにしかならないことでスレを私物化する行為に等しいよってことだ
655: 2021/07/05(月)08:27 ID:4kBMhQOc(1/3) AAS
>>653
>>603は調べたんかいな。cpprefjp な。
RVOを含めて調べれば、>>646だということは分かるだろ。
c++標準の扱いはcpprefjpの参照リンクにもある「値のコピー省略の保証について」が良くまとまっている。

検索・調査能力が低いのは今どきのプログラマーとして致命的欠陥だから、日頃から訓練したほうがいい。
656
(1): 2021/07/05(月)08:31 ID:4kBMhQOc(2/3) AAS
補足。
>>653の2はNRVOだからRVOとは別物な。
NRVOは最適化可能だけどコピー省略は保証されていない。
657
(2): 2021/07/05(月)08:44 ID:4kBMhQOc(3/3) AAS
>>656
あ、間違えた。NRVOとは関係ないや。

ついでに。
>しかしhogeはその後使っていないのだから、コンパイラ的には3はmoveになる余地があるはず

副作用のあるコピーコンストラクタがあったら最適化はやばいんじゃない?
規格上許されていたっけ?
658
(1): 2021/07/05(月)11:05 ID:w3Zb0u1p(1) AAS
ライフタイムを推論してcopy/moveの振り分けは理論上可能かもしれないが、現行の規格はそんなことは要求しない
lvalueからならcopy、rvalueからならmove
lvalueからmoveしてほしいならstd::moveしなさい
lvalueを渡しているのに勝手にrvalue referenceとして解釈されてぶっ壊されてたまるかよ
659: 2021/07/05(月)12:24 ID:M+MHtMKE(1/2) AAS
template<class T>
class A {
public:
A()=default;
A(T&&);
};
この場合、T==Aになるとmoveとcopyを兼ねる?
660: 2021/07/05(月)13:59 ID:MxHqaq3M(1) AAS
C++が出来るとは規格書がちゃんと読めることを言うんだね
661
(1): 2021/07/05(月)15:27 ID:NDiogwds(1) AAS
Macのclang++でコンパイルしています。
cstdlibをインクルードしなくてもrand()が使えてしまうのですが、これはなぜでしょうか?
662: 2021/07/05(月)15:36 ID:M+MHtMKE(2/2) AAS
規格票には規格書なんて書いてない
俺はちゃんと読めるんだなんて
イキッてるやつはブーメランだな
663: 2021/07/06(火)00:27 ID:86XKd96p(1) AAS
>>657
許されてるよ
その状況でコピコンやムーコンが呼ばれるかどうかは未規定(呼んでも呼ばなくてもいい)
というかこの「呼ばなくてもいい」っていう規定こそが正に規格がNRVOを認めてる部分そのもの
664: 2021/07/06(火)03:32 ID:PiE4/OQH(1) AAS
実際、「move さえ省略してほしい」って思惑で
auto hoge = func();
と書くところを
auto&& hoge = func();
と書いてる人なんているの?
665: 2021/07/06(火)07:29 ID:6WiwYssU(1) AAS
いるよ。
666
(1): 2021/07/06(火)07:45 ID:FcxtUR1g(1) AAS
>>657
エピステーメーも同じようなこと言ってたけどね
まぁコピーコンストラクタとかにコピー以外の副作用入れる方が悪い、ってことだろ
実際変な副作用など無いことを前提にしなきゃ出来ない最適化他にもあるやろ
667: 2021/07/06(火)10:03 ID:t2+Z62DR(1) AAS
>>661
stdlib.hにも定義されているが、他のヘッダをincludeすると、
その中から別のヘッダをincludeしている場合も有り、その中からさらに
別のヘッダをincludeしている場合も有る。
また、標準ではstdlib.hやcstdlibで定義されているとされていても、
その他のヘッダで定義されていないとも限らない。
668
(6): ◆QZaw55cn4c 2021/07/06(火)20:25 ID:/lKUoH39(1) AAS
>>666
>コピーコンストラクタとかにコピー以外の副作用入れる方が悪い
規格票のどこに?
669: 2021/07/06(火)23:17 ID:2d1Iatqp(1) AAS
>>668
規格票持ってるんですか?
670: 2021/07/07(水)00:20 ID:ACi5C/C8(1) AAS
>>668
コイツたまにトリップ外すの忘れて荒らしみたいなことしてんの最高に滑稽
671
(1): はちみつ餃子 ◆8X2XSCHEME 2021/07/07(水)05:18 ID:BiM5c4gH(1) AAS
>>668
副作用がある場合でも省略されるというのは明記されている。

外部リンク[copy]:timsong-cpp.github.io
> even if the copy/move constructor and/or destructor for the object have side effects
672
(1): 2021/07/10(土)14:04 ID:yQTcABkI(1) AAS
>>658
3がmoveになったところで何も壊れるものは無くね?
というのと、take_S()に渡される方がぶっ壊されることにはならないので
3がmoveになってもlvalueとして渡されることには変わりは無い
673: 2021/07/11(日)00:07 ID:5nx6GB9W(1/5) AAS
>>672
外部リンク[html]:cpplover.blogspot.com
とりあえずこれとか読んでからお願いします
全体的に何が言いたいかよく分からないですがmoveならrvalueとして渡されるのでそこは理解してください
674: 2021/07/11(日)00:24 ID:YJk6tGcw(1/11) AAS
>全体的に何が言いたいかよく分からないですが
ヒエッ……このスレは荒れる……
675: 2021/07/11(日)00:27 ID:YJk6tGcw(2/11) AAS
>moveならrvalueとして渡されるのでそこは理解してください
rvalueになるのは移動の右辺であり3のケースでは(3がmoveになったとして)移動元のhogeの実体だが
take_S()に渡るのはmoveされた後のhogeなのでtake_S()の中では問題無くlvalue扱い
676: 2021/07/11(日)00:28 ID:YJk6tGcw(3/11) AAS
しつれい、
誤: take_S()に渡るのはmoveされた後のhoge
正: take_S()に渡るのは&hogeからmoveされてきたhogeの「複製」
677
(1): 2021/07/11(日)00:51 ID:5nx6GB9W(2/5) AAS
リンク先読んだ?
678: 2021/07/11(日)00:53 ID:YJk6tGcw(4/11) AAS
もとから読んでるっつーの;;;
>>677はムーブコンストラクタで構築されたオブジェクトがlvalueでないと思っちゃうタイプ?
679
(3): 2021/07/11(日)00:54 ID:5nx6GB9W(3/5) AAS
3.でmoveは発生しません
詳細はさっきのブログ記事に書いてあります
以上
680: 2021/07/11(日)00:55 ID:YJk6tGcw(5/11) AAS
>>679
どこか指摘できずに逃亡;;;
681: 2021/07/11(日)00:57 ID:5nx6GB9W(4/5) AAS
lvalueをmoveせよ

さて、2. はどうしたらいいだろう。moveコンストラクタを実装したものの、コンパイラは2. の場合には、moveコンストラクタを呼び出してくれない。なぜなら、コンパイラは、プログラマの脳内仕様を読んではくれないからだ。tmpが、その後に使われていないかどうかは、コンパイラは静的に決定できないのである。

そこで、プログラマが意図を伝えてやらなければならない。

X b( static_cast<X &&>(tmp) ) ;

この様に、rvalueにキャストしてやれば、moveコンストラクタを呼び出すことが出来る。
682: 2021/07/11(日)01:01 ID:YJk6tGcw(6/11) AAS
>>679はSのインスタンスhogeを関数void take_S(S) (※void take_S(S&)ではない!)に渡す際に、
take_S()の呼び出し元(この場合main())が
hogeと同じ値を持つインスタンスをtake_S()の引数用領域に構築する必要がある、というあたりからして理解していないのではないか;;;
で、問題にしているコードはリンク先の
>tmpが、その後に使われていないかどうかは、コンパイラは静的に決定できないのである。
には該当しない
683: 2021/07/11(日)01:04 ID:YJk6tGcw(7/11) AAS
なぜなら、今回のケースはコードを見たらワカルからじゃわ;;;
コンパイラは静的に決定できない、と言っているのは停止性問題を解く万能のアルゴリズムが無いことから来ているが、
特殊なケースでは停止性問題は機械的に解ける
今こそその時、

、というあたりからして>>679はちんぷんかんぷんなのではないか……
684
(1): 2021/07/11(日)01:11 ID:5nx6GB9W(5/5) AAS
あーそこがわかってなかったのね
take_Sの仮引数を実引数で初期化する時に同じことが起こるだけですよ?
実引数をrvalue参照とみなしてオーバーロード解決できればmoveで仮引数が初期化される
できなければ(かつlvalue参照として解決できれば)copyで仮引数が初期化される
685
(1): 2021/07/11(日)01:24 ID:YJk6tGcw(8/11) AAS
>>684
藻前の頭が固いだけなんとちゃうか;;;

>実引数をrvalue参照とみなしてオーバーロード解決できればmoveで仮引数が初期化される
この場合(すなわち実引数hogeをtake_S()の仮引数としてコピーした後呼び出し元が実引数hoge()を使わない(ことをコンパイラが機械的に判定できる)ケース)
において、実引数hogeのアドレスをrvalue参照とみなしてはいけないという根拠は?
論理的にはソースコードの意味を変えることなく整合するんだけどそういう最適化はいけないことなの?
686: 2021/07/11(日)02:58 ID:YJk6tGcw(9/11) AAS
んまーとは言ったものの、
【実験1】 >>627のコードをループにしてやって最適化「-O2」にしても"move"にならなんだorz
外部リンク:wandbox.org
結果:
default
--------
copy
0, 1
default
--------
省4
687: 2021/07/11(日)02:59 ID:YJk6tGcw(10/11) AAS
【実験2】 もちろんstd::move(hoge)したらmoveになる
(上記リンク先のコードのDO_MOVE定義のコメントアウトを外してを有効化)
結果:
default
--------
move
0, 1
default
--------
move
省10
688
(1): 2021/07/11(日)03:09 ID:YJk6tGcw(11/11) AAS
(言い訳1)
実験3のような最適化が許されるのだから、copyをmoveに読み替える最適化も許されるべきだ
規格に照らしてどうなのかはC++規格の専門家の反応待ち

(言い訳2)
今回のケースでGCC様がcopyをmoveにする最適化を拒むのは、単にhogeの使用箇所の分析をサボっているか
(データフロー解析の一環として論理的には十分take_S()呼び出し後の未使用を機械的判定をやれるはずなのに…
、デストラクタのdefault[] のコストでも気にしている可能性が微レ存

(言い訳3)
>>627のコードでmoveになる、と最初に言い出したのは>>609であって漏れではない
むしろ漏れは「場合によってはcopyが起きる」(>>623)と述べてたのでcopy派である
省1
689: 2021/07/11(日)13:04 ID:G2C/uXds(1) AAS
>>685
> 論理的にはソースコードの意味を変えることなく整合するんだけどそういう最適化はいけないことなの?

コピーコンストラクタとムーブコンストラクタのどっちが呼ばれたかわかるようにログ出力とかしてたら動作が変わる。
そういう副作用を含めてコンパイラが動作を変えていいケースは >>671 で挙げられたように明示的に規定されていて、
あなたの言うケースはそうではない。
690
(1): はちみつ餃子 ◆8X2XSCHEME 2021/07/11(日)18:47 ID:8K44AFaV(1) AAS
>>688
Copy になるべき場合と Move になるべき場合は条件がはっきりしている。
どちらでもいい場合は無い。

表層上の動作が仕様通りであればどうコンパイルしても良いのが C/C++ なので、
あえて、あくまでもあえてレアケースを挙げるとすれば
(見かけ上の) 動作が Copy でも Move でも同じだとコンパイラが見ぬくことが出来る場合が
あったなら Copy の場面で Move 相当の機械語が生成されることが絶対にないとは言いきれないけども、
Copy でも Move でも同じだと確信できる場合に限られるので動作からはどうせ観測できない。

意味を変える最適化をしていいという唯一のルールがコピー (またはムーブ) の省略で、
その一部が C++17 では必須化されたわけだね。
691
(9): 2021/07/12(月)07:46 ID:5HFqt1x5(1/3) AAS
ある整数がある整数の n 乗であることの判定ってどうするのが良いでしょうか
(n も整数とします)

今までは
x == (int)pow((int)pow(x, 1.0/n), n)
で判定してたんですが、今の自分の環境で x = 4096、n = 6 を渡したら誤判定しました

(int) を round に変えるのを思いつきましたが、コーナーケースがあったら嫌なので、他の良い方法があったら教えてください
692
(2): 2021/07/12(月)08:17 ID:K0Wntvol(1) AAS
>>691
諦めてboostの多倍長整数を使う。
693
(4): 2021/07/12(月)08:25 ID:Vv9VoiuP(1) AAS
>>691
double y = pow(x,1.0/n);
int iy = (int)y;
iy==y
このほうが多少マシにはなると思うが根本的な解決になってないので
double epsilon = 0.00000001;
y-iy < epsilon;
にするとか
694
(2): 2021/07/12(月)09:45 ID:Q0n0f8DA(1) AAS
>>691
どこまで高速化したいのかわからんけど頑張ってn乗計算するとか
外部リンク:qiita.com
695
(4): 2021/07/12(月)10:01 ID:5HFqt1x5(2/3) AAS
>>692
多倍長整数でどうやるんでしょうか?

>>693
確かに、改めて n 乗する意味なかったですね

>>694
後出しですみませんが、遅くて良いから短くて誤判定のないのが望ましいです
696
(5): 2021/07/12(月)10:11 ID:5HFqt1x5(3/3) AAS
>>693
y の小数部分が 0.9999999998 とかだと失敗しますよね?
iy = round(y) として abs(y - iy) < 1e-12 で判定しようかなと思います
697
(1): 2021/07/12(月)10:22 ID:D0qCNAQT(1/2) AAS
>>690
最後だけ認識おかしい、唯一ではない
698
(1): 2021/07/12(月)12:24 ID:uJpO0uZ2(1/2) AAS
>>697 他に何かあるなら教えて。
699
(1): 2021/07/12(月)12:35 ID:4jaglyfV(1/2) AAS
>>695
boost 多倍長整数 冪乗 で検索。
書くのは色々と面倒だから、解説ページ読め。boost はpowも対応している。
700
(1): 2021/07/12(月)17:41 ID:D0qCNAQT(2/2) AAS
>>698
わかりやすいとこで言えばStrict Aliasing Rulesとか
型が違おうが何だろうが、本来一度書いたものが、次別のポインタ(or参照)を読む時同じ場所だったら、さっき書いた値になってなければならない
・・・んだが、そんなこと守ってたら最適化なんかほとんど出来ないだろ
他にC++の仕様に規定されてなくとも各コンパイラは色々やってる
大抵は問題ないが、ごくまれに意図した挙動になってくれなくて困ることはあるぞ
701
(3): 2021/07/12(月)18:26 ID:3yd7dMb1(1/5) AAS
>>691
>>692
アホな文系の質問にアホな文系が答えるスレ?

どの値が与えられて、その値の条件(範囲、符号、...)は何か
環境は仮定していいのか、(C++の規格範囲内の)すべての環境で正しく動作する必要があるのか
コードに求めるものは何か?(可読性、速度、...)
をはじめからすべて書きなさい
702
(5): 2021/07/12(月)18:32 ID:3yd7dMb1(2/5) AAS
ごく一般的なPC環境で、与えられた整数がintの範囲であれば、
(ある程度の判別を行ったあと)普通に四捨五入で良い

n乗根の候補を求めたあと整数領域でn乗してもいいし
元の数を(割り切れる判別をしながら)候補で割っていってもいいし
与えられた整数が32bitの範囲であれば、2分検索やリニア検索してもいい

アホな文系が理解できる範囲で自分の頭で考えて自分の責任でコードを書きなさい
703: 2021/07/12(月)19:47 ID:F4g5ptiT(1) AAS
>>701
そういった諸々の細かい調整を諦めて多倍長整数を使う、ということだよ。
そもそもの要件(n乗判定)でpowを使う乱暴さを考慮すれば、面倒な部分を処理してくれるライブラリを使用するのは有力な選択肢。それを無視して「アホな文系」とは言ってくれる。

ご高説を宣ってくれた後にどんな素晴らしい解説を>>702でしてくれるのかと思ったら、n乗判定にわざわざ割り算を持ち込んだり、対数にも触れずに検索にフッ飛ぶ滅裂ぶり。>>601が混乱するのを笑うために書き込んでいるとしか思えん。

文系、文系と馬鹿にする人間は、人間と会話のできない発達障害が多いのかね?
704
(1): 2021/07/12(月)20:05 ID:3yd7dMb1(3/5) AAS
ヒント
多倍長整数を使っても何も解決しない
705: 2021/07/12(月)20:29 ID:4jaglyfV(2/2) AAS
>>704
なんで解決しないのか解説してもらいたいねぇ。
706: 2021/07/12(月)20:34 ID:rFlF3L7g(1) AAS
累乗根は浮動小数点の演算だからだよ
707
(1): 2021/07/12(月)20:52 ID:xS7m7lUb(1/2) AAS
いや累乗して整数同士で比較すりゃええやん
708
(1): 2021/07/12(月)21:00 ID:+DCDGa5F(1) AAS
n乗数判定は明らかに整数論の問題なんですがそれは

なお一番簡単な平方数判定でもNPなんで(一発でポンと答えが出る楽な方法は多分)ないです
709
(1): 2021/07/12(月)21:13 ID:q3a62lD+(1) AAS
因数分解してハッシュで数えて全部6の倍数なら何かの6乗なんじゃないの

4096=2^12

h{2}→12個

12は6の倍数なので何かの6乗

3*7*3*7*3*7*3*7*3*7*3*7 = 85766121 だと
省3
710
(1): 2021/07/12(月)21:14 ID:M5TNNHP+(1) AAS
累乗根の演算で引数の逆数をどうやって整数で表現するの?
>>691の例で言えば、n=6なら6乗根(=1/6乗)の計算を行なっている
711
(1): 2021/07/12(月)21:21 ID:uJpO0uZ2(2/2) AAS
>>700
未定義動作となる場合はそもそも「意味」が定まらないので「意味を変える最適化」とかいう話にならないよ。
712
(2): 2021/07/12(月)22:14 ID:vW8lyXRJ(1) AAS
ひさしぶりにみると
すごく
カオスなスレッド
713: 2021/07/12(月)22:33 ID:j4Yh95VG(1) AAS
>>709
>>702 が言ってるのがそれじゃ無い?
> 元の数を(割り切れる判別をしながら)候補で割っていってもいいし
2で割り切れなくなるまで割り、割った回数がnの倍数で無ければNG
3で割り切れなくなるまで割り、割った回数がnの倍数で無ければNG
を繰り返すって事かと(多分)
714
(1): 2021/07/12(月)22:51 ID:MoTlox7M(1) AAS
数値計算としては>>693,696がもっとも正統派の方法だよ
素直に累乗根を求めて誤差を評価して判定する
わざわざトリッキーな手段を採る必要性は無い
715
(1): 2021/07/12(月)23:38 ID:PjBVtdER(1) AAS
>710
「 累乗の判定」と「 累乗根の演算」をごっちゃにしている?

「累乗根の演算」はあくまで「 累乗の判定」の候補となる整数を
見つける手段の一つで、必ずしも必要ではない。
極端な話、候補となる整数を2から順番に数えて判定しても良い。
まあ、「できるだけコードを簡単に」という話なら素直に累乗根を
使ったほうが良いけど、その時でも(累乗/累乗根計算の誤差の問題から)
「 累乗の判定」を行う必要がある。

>693 >714
よくよく>691を見たら、本質的にはintによる切り捨ての問題だな。
省7
716
(1): 2021/07/12(月)23:48 ID:3yd7dMb1(4/5) AAS
長々と書いてやっと質問者と同レベルに追いついた
アホな回答者

全部>>702に書いてるし
717: 2021/07/12(月)23:51 ID:3yd7dMb1(5/5) AAS
ある整数やnがマイナスの場合に言及してるのは>>701だけ
質問者も他の回答者もそこまで頭がまわらない
718: 2021/07/12(月)23:57 ID:xS7m7lUb(2/2) AAS
そっかあ
あたまがいいんだね
719
(1): 2021/07/13(火)00:17 ID:u8F7J+OY(1/10) AAS
>>699
いや、
整数 x、y、n が与えられたときに x が y の n 乗であるかどうか判定する
ではなく、
整数 x、n が与えられたときに x が y の n 乗となるような整数 y があるかどうか判定する
ですよ?

多倍長整数なんて出る幕ないでしょう
もしかして y を全ての自然数について全探索するのを想定してる?
高卒?
720
(1): 2021/07/13(火)00:31 ID:u8F7J+OY(2/10) AAS
>>701
質問者自身が int にキャストとか round とか言ってるんだからどう見ても自然数の話でしょ
バカ

>>702
> n乗根の候補を求めたあと整数領域でn乗してもいいし
> 元の数を(割り切れる判別をしながら)候補で割っていってもいいし
なんで今更質問者(>>696)より筋の悪い方法を提案するの?笑

> 与えられた整数が32bitの範囲であれば、2分検索やリニア検索してもいい
これしきの問題で何を探索することがあるんだよバァ〜〜〜カ
つーかわざわざ二分探索とかするならそれこそ桁数めっちゃ多いときの方が有効だろ
省1
721: 2021/07/13(火)00:34 ID:u8F7J+OY(3/10) AAS
>>707
えっっっっ
やっぱり根を探索するつもりだったんだ
ヤベーなお前
722: 2021/07/13(火)00:38 ID:u8F7J+OY(4/10) AAS
>>708
何と勘違いしてんのか知らんが、ここで与えられてる問題は桁数 n に対して明らかに O(n) で解けるだろ
アホ
1-
あと 280 レスあります
スレ情報 赤レス抽出 画像レス抽出 歴の未読スレ AAサムネイル

ぬこの手 ぬこTOP 0.058s