C++相談室 part131 at TECH
[2ch|▼Menu]
[前50を表示]
950:デフォルトの名無しさん
17/10/07 16:14:50.00 Mcd7mBScM.net
std::vector<any_struct_t> ret(index_list);
std::transform(index_list.cbegin(), index_list.cend(), ret.begin(), [&array](auto i){ return array[i]; });

951:デフォルトの名無しさん
17/10/07 16:25:34.07 jvf7kHO4M.net
>>924
それタイプミスあります?
でももう一つ配列を用意してコピーする点では
他の方と一緒ですね
別配列を用意せず全てswapで済ます方法も作ってみましたが
これにはindex_listが更に2本必要になり
効率は別配列と変わらないと予想される結果でした
参考になりました
ありがとうございました

952:デフォルトの名無しさん
17/10/07 16:38:58.22 Mcd7mBScM.net
一行目初期化はsizeだった
すまん

953:デフォルトの名無しさん
17/10/07 16:55:14.57 rHfSD+zL0.net
>>925
別領域を全く使わずin-placeでかつ汎用性のあるやり方ってすごく難しそう。
でも不可能性の証明も難しそうなんだよな。

954:デフォルトの名無しさん
17/10/07 17:23:03.40 9j2tI+ab0.net
index_list に含まれる値がそれぞれ重複なく1回だけ出現とか、
いかにも破られそうな条件を暗黙に期待するライブラリ、
てのも変な感じだしねぇ。

955:デフォルトの名無しさん
17/10/07 17:39:38.90 7nonADk70.net
任意の置換は互換の積で表せるので、swap繰り返せばin-placeで可能。
URLリンク(rikei-index.blue.coocan.jp)

956:デフォルトの名無しさん
17/10/07 17:47:14.55 IjrnmnS30.net
>>906
URLリンク(ideone.com)
こういうことでしょ?

957:デフォルトの名無しさん
17/10/07 18:00:13.73 rHfSD+zL0.net
>>929
まだやってない場所どこだっけ?

958:デフォルトの名無しさん
17/10/07 18:14:41.26 7nonADk70.net
>>927
「別領域を全く使わず」を見落としてたすまぬ

959:デフォルトの名無しさん
17/10/07 18:35:30.53 rHfSD+zL0.net
「別領域を全く使わず」とはいっても、テンポラリの変数を1個とか2個の固定数だけ使うのは除く。

960:デフォルトの名無しさん
17/10/07 19:11:01.43 7nonADk70.net
屁理屈を言うと、index_listを壊していいなら、
以下の手順で別領域を使わない置換は可能。遅いけど。
for( size_t i = 0; i < array.size() - 1; ++i )
{
std::swap( array[i], array[index_list[i]] );
std::swap( index_list[i], *std::find( index_list.begin()+i+1, index_list.end(), i ) );
}

961:デフォルトの名無しさん
17/10/07 19:26:56.50 7nonADk70.net
おっと、index_list.begin()+i+1の「+1」は消してくれ

962:デフォルトの名無しさん
17/10/07 19:44:23.58 rHfSD+zL0.net
この話をきっかけに、std::next_permutation の仕様を見てみたが、どういう時に使うのかよくわからない。

963:デフォルトの名無しさん
17/10/07 20:14:16.81 jvf7kHO4M.net
流石にO(n)は維持しないと
厳しいと思います

964:片山博文MZ
17/10/07 20:23:01.47 vDiuGwTad.net
お前ら、プログラム書くとき、普通にnoexceptを何回も書いてるの?

965:片山博文MZ
17/10/07 20:25:42.72 vDiuGwTad.net
>>936
permutation を実装するときに決まってんだろ?

966:デフォルトの名無しさん
17/10/07 20:53:48.18 Mcd7mBScM.net
>>938
今までthrow()と書いてた場所には書いてるよ
むしろ、書いてないの?

967:片山博文MZ
17/10/07 21:02:34.40 vDiuGwTad.net
>>940
コンパイラーのバカ。

968:はちみつ餃子
17/10/07 21:05:19.53 JUuMz14c0.net
>>918
any は C++17 で標準に入ったよ。

969:デフォルトの名無しさん
17/10/07 21:13:10.52 x4ka+ayCr.net
規格と規格じゃないものの区別も付かない低能はすっこんでて

970:900
17/10/07 21:13:19.89 m/msdGTM0.net
>>908
ありがとうございます。
いくら検索しても出て来ないので、困ってました。

971:デフォルトの名無しさん
17/10/07 21:17:07.24 rHfSD+zL0.net
>>939
わからんがな

972:デフォルトの名無しさん
17/10/07 23:13:09.50 7nonADk70.net
>>934
別領域を使わない置換に再挑戦。今回はO(n)のはず。
for( size_t i = 0; i < array.size() - 1; ++i )
{
size_t j = i, k = index_list[i];
while( k != i )
{
std::swap( array[j], array[k] );
index_list[j] = j; j = k; k = index_list[k];
}
index_list[j] = j;
}

973:デフォルトの名無しさん
17/10/08 00:16:09.42 FGX6bPrh0.net
>>9


974:46 二重ループなのにO(n)なの?



975:デフォルトの名無しさん
17/10/08 00:28:37.42 wi1g/BWB0.net
後出しのようで心苦しいけどindex_listを壊すのはダメだと思う。
const参照で渡すインタフェースにできないという意味で汎用性条件を満たしていない。

976:デフォルトの名無しさん
17/10/08 06:22:19.14 +SudLjvR0.net
>>947
以下の2つの理由により、外側のループがn回まわる間に
内側のループの中身はたかだかn回しか実行されない。
1. 内側のループ内で処理済みのインデックスjに対し index_list[j]=j が実行される。
2. index_list[i]==i の条件が最初から満たされていた場合、内側のループは実行されない
要するに、内側のループを実行済みかのフラグとしてindex_listを使ってるだけ。
>>948
index_listを壊している時点で屁理屈なのは自覚しているんで、仕方ない。
一応、別配列にムーブする場合と比べると、
最初から正しい位置にある要素への処理が不要になるというメリットは有る。

977:デフォルトの名無しさん
17/10/08 11:20:44.83 HosRocIl0.net
>>928, >>948
ライブラリに対するオレオレ定義をいちいち開陳しなくていいよ、チラ裏にでも書いとけ

978:デフォルトの名無しさん
17/10/08 11:34:33.36 +SudLjvR0.net
駄目な理由が引数を壊すってことだけなら、引数を値渡しにしてやれば、
呼び出し時に勝手にコピーされるので問題ないはず。
壊していい引数を渡す時はstd::move()すればいいし。

979:デフォルトの名無しさん
17/10/08 13:39:35.60 GUxnbDfL0.net
引数がconst参照=引数の状態を変更しない(てか、できない)という意思表示
に対して
引数が右辺値参照=引数の状態を変更する(しても文句言うな)という意思表示
というのはアリ?
右辺値参照に対する理解が曖昧なんで漠然とよく分からない(何が分かって
ないかも分からないw)んだが、もっと別な意思表示方法もある?

980:デフォルトの名無しさん
17/10/08 16:07:31.29 6tf5QjxV0.net
ほ〜ん>>946の奴はちゃんと動いたわ;
URLリンク(ideone.com)

981:デフォルトの名無しさん
17/10/08 16:11:39.00 6tf5QjxV0.net
>>946の奴は要素[i]が内側のwhile()ループからは1回以上アクセスされないから確かにO(N)な気配、

982:デフォルトの名無しさん
17/10/08 23:25:19.93 sIfqyVAH0.net
右辺値参照はさっぱり意味わからんわ。

983:デフォルトの名無しさん
17/10/09 09:00:03.09 U0LcPFS10.net
右辺値参照というのは、関数f()へのT型データの値渡し時に暗黙のうちに行われる(C++03までは無条件に行われていた)
 (左辺値) = (右辺値)
という代入処理において、
当該代入処理後、右辺値が関数呼び出し元によって使われなくなることが明白なとき、
 左辺値へのコピー後、右辺値をデストラクトする
という処理に暗黙のうちになっていたものを、
 右辺値から左辺値への移動
と「も」書けるようにするためのしくみ
Tに効率の良いムーブコンストラクタ(か右辺値参照を引数とする代入演算子)を定義しないとメリットが生じない
ポインタに__restrictを付けるべきかどうか悩まねばならないレベルの人用
C++03でもコンストラ・デストラ呼び出し回数削減の最適化がかかって同じような効果になるケースが多々あるから
そういうのが信用できない神経質な人向け
※ 個人の感想です

984:デフォルトの名無しさん
17/10/09 09:09:56.49 Ge9OzZ/lr.net
それで>>952の質問の答えはどうなるんだ?

985:デフォルトの名無しさん
17/10/09 09:20:15.73 U0LcPFS10.net
>>957
右辺値参照には一時オブジェクトしか代入できない縛りがあるから_
関数fooを
 voiid foo(int&& x)
というバージョンしか定義していないとすると、
 int g_x = 10;
 foo(g_x);
がビルドが通らないのではないか;
一般的な使用を想定すれば、結局foo(const int& x)も定義必要
C++03までしか使ったこと無いから知らんけど;;

986:デフォルトの名無しさん
17/10/09 09:37:56.10 nhJ4ZLVgM.net
>>958
その場合はfoo(int(g_x));が通るから、必須ではないよ
コピーを外側で明示的にやらせることで、こっちのほうが責任が明確になるので好きという人もいる

987:デフォルトの名無しさん
17/10/09 10:15:14.60 53KUOYPr0.net
必然性の無い実装都合のシンクはクソ

988:デフォルトの名無しさん
17/10/09 17:26:43.28 bLguG3ky0.net
オブジェクトのコピーとかムーブのためにここまで言語仕様を複雑にしないといけないのか。おれにはさっぱり理解不能だわ。

989:デフォルトの名無しさん
17/10/09 17:57:29.04 0USm99MRM.net
俺も右辺値参照はどうかと思う
いらないよね

990:デフォルトの名無しさん
17/10/09 18:35:18.07 3udUYydoM.net
使わなくてもいいんじゃないか?
使ったことないから複雑に感じるだけで、そこまで複雑でもないよ

991:デフォルトの名無しさん
17/10/09 18:45:40.84 UEIAYP2F0.net
>>961
GCをもたない言語の宿命だから嫌なら性能を犠牲にするかGCを持つ言語を使えばいい

992:デフォルトの名無しさん
17/10/09 18:56:48.86 QjIlXwNcM.net
いやいやスマポがあるじゃない。
中級が多いプロジェクトならスマポ強制のほうが性能上がるんじゃないかと思う。

993:デフォルトの名無しさん
17/10/09 18:58:40.39 8DJAJvC20.net
個人的にはC++の言語仕様の暗黒面はほとんど「参照」が絡んでいると思う。

994:デフォルトの名無しさん
17/10/09 19:50:58.39 3udUYydoM.net
ADLとか部分特殊化のマッチとかのほうが、はるかに複雑で暗黒だと思う

995:デフォルトの名無しさん
17/10/09 20:54:40.71 bLguG3ky0.net
>>964
理解してないのでなにを指摘してるかさっぱり分からないが、
つまり、気取ってC++でGCっぽいことしようとして破綻してるわけだな。

996:デフォルトの名無しさん
17/10/09 20:56:32.03 UEIAYP2F0.net
>>968
> 理解してないのでなにを指摘してるかさっぱり分からないが、
わからないなら絡んでくるなよ...
> つまり、気取ってC++でGCっぽいことしようとして破綻してるわけだな。
全然違うし

997:デフォルトの名無しさん
17/10/09 20:56:47.16 1ynB1O3m0.net
>>967
そう思う。
そのへんは「ルール」でしかないけど、右辺値参照はそれ自体が左辺値参照とは違うひとつの概念だから理解可能

998:デフォルトの名無しさん
17/10/09 21:28:57.78 iWLkHfj90.net
右辺値参照なんか、破壊不可オブジェクトをムーブするときくらいしか使わないような。うにーくぽいんたとか。
それ以外は参照でいいし。

999:デフォルトの名無しさん
17/10/09 21:45:04.70 Rk3/uNWr0.net
右辺値参照の有用性を理解できない人間にとってはそもそもC++自体が無用だと思う
さっさと退散しなさい

1000:デフォルトの名無しさん
17/10/09 21:56:43.96 bLguG3ky0.net
ところでなんでそんなに一時オブジエクトを参照しなきゃいけないコードを書くの?
参照元を管理するのが面倒だから? そういう人は初めからGC言語使えばよくね? ということですか?

1001:デフォルトの名無しさん
17/10/09 22:03:17.69 Rk3/uNWr0.net
なんでとか言われても。。。
壊してもいい一時オブジェクトの場合、特別に効率的な扱いをしたくなるケースなんて山ほどある
それが分からないならC++なんて触らずにGC言語専門でやってればいいと思うよ

1002:はちみつ餃子
17/10/09 22:10:35.64 GeS0S50a0.net
そのあたりはトレードオフなんだよ。
そりゃあ気にせずに済むなら気にしたくないが、気にしなきゃならないときに出来ることがないのはつらいって話で。

1003:デフォルトの名無しさん
17/10/09 22:13:59.60 0USm99MRM.net
俺もわからん
左辺値参照ではなく右辺値参照を使った方が
良い状況ってどんなの?
あと唐突にガページコレクション出してるけど
何の関係があるの?

1004:デフォルトの名無しさん
17/10/09 22:24:17.86 bLguG3ky0.net
もしかしてC++で仕事したことないんですか?

1005:デフォルトの名無しさん
17/10/09 22:25:07.16 1ynB1O3m0.net
そりゃ右辺値を束縛したくてかつconst


1006:左辺値じゃダメな場合だろ



1007:デフォルトの名無しさん
17/10/09 22:43:46.89 0USm99MRM.net
んー?
結局無いんでしょ?
使うべきシチュが
そうならそう言えばいいのに

1008:デフォルトの名無しさん
17/10/09 22:45:47.51 jvobj8TT0.net
>>979
classの初期化はどう?

1009:デフォルトの名無しさん
17/10/09 22:51:16.17 UEIAYP2F0.net
使うシチュエーションがない?
規格決める奴等が無駄にあーだこーだ言ってるだけとか思ってるなら病院に行った方がいいと思う

1010:デフォルトの名無しさん
17/10/09 22:54:00.89 0USm99MRM.net
初期化はどう?って言われても・・
右辺値参照で初期化するのがベターな状況は
浮かびませんけど

1011:デフォルトの名無しさん
17/10/09 22:55:12.55 0USm99MRM.net
>>981
と言いつつも
思い浮かばないんでしょ?
じゃあ君もワイと一緒ですね

1012:デフォルトの名無しさん
17/10/09 23:09:59.39 1ynB1O3m0.net
んん?
右辺値を束縛したい(一時オブジェクトだから左辺値としての実体はない)
けどconst左辺値じゃダメ(中身を変更したいから)
 ↑
これのどこにわかりにくい点があるというのか?
「RVOが保証されるようになったらいらない」という意見なら理解できるが・・・

1013:デフォルトの名無しさん
17/10/09 23:14:06.35 1ynB1O3m0.net
たとえば swap の実装なんか(素朴には)moveを3回繰り返すんだから
右辺値参照の有用性は明らかだろ

1014:デフォルトの名無しさん
17/10/09 23:16:20.29 7RyTvmhPr.net
>>973「なんでそんなに一時オブジエクトを参照しなきゃいけないコードを書くの?」
 ↓
>>984「右辺値を束縛したい(一時オブジェクトだから左辺値としての実体はない)けどconst左辺値じゃダメ」
 「これのどこにわかりにくい点があるというのか?」
これがアスペというやつか

1015:デフォルトの名無しさん
17/10/09 23:20:00.09 1ynB1O3m0.net
>>986
は?
>>979に言ってるんだよ

1016:デフォルトの名無しさん
17/10/09 23:25:56.07 0USm99MRM.net
>>985
これを右辺値参照Verに書き換えて
利点を示してもらえますか?
void swap(int& a,int& b)
{
int c = a;
a = b;
b = c;
}
void main()
{
int a = 1;
int b = 2;
swap(a,b);
}

1017:デフォルトの名無しさん
17/10/09 23:26:35.20 1ynB1O3m0.net
>>986
そっちこそ唐突に>>793>>984を唐突に矢印で結び付けてるけど大丈夫か?
お前の脳内の連想なんて誰にもわからないぞ

1018:デフォルトの名無しさん
17/10/09 23:27:28.76 1ynB1O3m0.net
>>988
利点はない
intだもの

1019:デフォルトの名無しさん
17/10/09 23:31:15.79 0USm99MRM.net
なら何なら利点があるの?
long long型ならあるの?
もう訳が分からないよ

1020:デフォルトの名無しさん
17/10/09 23:32:58.04 1ynB1O3m0.net
>>991
コピーコストの大きいコンテナだったら三回も代入したくないだろ?

1021:デフォルトの名無しさん
17/10/09 23:34:48.01 jvobj8TT0.net
>>982
もう使わないなら右辺値参照版のコンストラクタに渡したほうがいいじゃん
そしたら、コピーが起きなくて済むでしょ?

1022:デフォルトの名無しさん
17/10/09 23:41:18.28 U0LcPFS10.net
>>986
右辺値を束縛したい文脈ではかわりにconst左辺値で常におkなのでは…(ていうかconstはあってもなくても良い
>>985
T型データのswapは素朴にはT型データのコピー3回+破棄2回ぐらいが生じる
のでわ…

1023:デフォルトの名無しさん
17/10/09 23:48:51.82 bLguG3ky0.net
swapが頻繁に起こるような用途なら、なんではじめからポインタで管理しないんですか?

1024:デフォルトの名無しさん
17/10/09 23:49:46.71 qIHa8iWG0.net
一時オブジェクトもglvalueなんだから
T &に束縛できればよかった

1025:デフォルトの名無しさん
17/10/09 23:52:41.96 jvobj8TT0.net
>>995
ヒープじゃなくてスタックで処理したいから

1026:デフォルトの名無しさん
17/10/09 23:55:42.49 0USm99MRM.net
結局のところ
右辺値参照はコピーコストを削減出来るのが利点で
それぐらいしか使い道がないってことか
かつ、コピーコンストラクタよりムーブコンストラクタの方が
コストを軽く出来るクラスに限られると
struct a{ void* p; }; // これには効果が期待出来るが
struct b{ int p[65536]; }; // これには効果は期待出来ない
結論としては、やっぱいらねーやこんなのってことだな

1027:デフォルトの名無しさん
17/10/09 23:58:36.68 jvobj8TT0.net
後者も効果が期待できるよ
そして、コピーコストが削減できるだけってのは正しいが、いるかいらないかは人による

1028:デフォルトの名無しさん
17/10/10 00:01:39.19 O5j+wjNW0.net
>>998
> struct b{ int p[65536]; }; // これには効果は期待出来ない
それはあんたがそんな構造をよく使うんなら正しい
よかったじゃないか、結論が出てw

1029:1001
Over 1000 Thread.net
このスレッドは1000を超えました。
新しいスレッドを立ててください。
life time: 72日 12時間 33分 11秒

1030:過去ログ ★
[過去ログ]
■ このスレッドは過去ログ倉庫に格納されています


最新レス表示
スレッドの検索
類似スレ一覧
話題のニュース
おまかせリスト
▼オプションを表示
暇つぶし2ch

556日前に更新/267 KB
担当:undef