[C++] コンパイラ頼り

25130
記事: 4
登録日時: 7年前

[C++] コンパイラ頼り

投稿記事 by 25130 » 7年前

日記やトピックを見てて薄々感じていましたが,
もしかして少数派ですか…?

CODE:

std::vector method(~) {
  std::vector local;
  (処理)
  return local;
}
とか割とやっちゃってたりしますね。
最後に編集したユーザー 25130 on 2017年12月12日(火) 23:21 [ 編集 1 回目 ]

アバター
usao
記事: 1889
登録日時: 12年前

Re: [C++] コンパイラ頼り

投稿記事 by usao » 7年前

じゃあ,こうかよ!

CODE:

std::vector && method(~){ ...(略) }
とか書いちゃったことがある人は挙手しましょう.
(^o^)ノ

戻り値はコンパイラが最適化してくれるとかいう話だけど,そこら辺の確実性(?)がよくわからんから

CODE:

//引数のvectorの内容を結果で上書きするよ!
void method( std::vector &rDstResult ){ ... }
とかいうのを書いちゃう.
最後に編集したユーザー usao on 2017年12月13日(水) 10:15 [ 編集 1 回目 ]

アバター
purin52002
記事: 235
登録日時: 8年前

Re: [C++] コンパイラ頼り

投稿記事 by purin52002 » 7年前

昔パターン認識の勉強をしてた時に結構大きめ(100とか1000とか)のvectorを使ったことがあります。

このころはcからc++へ移行したばかりだったのでこのような関数を使っていました

CODE:

//vectorとvectorを渡してvectorを返す
vector Func(vector x, vector y) { ... }
これを以下のように書き換えると

CODE:

//vectorの参照とvectorの参照を渡してvectorのポインタに書き込む
void Func(const vector &x, const vector &y, vector *z) { ... }
実行に1分かかっていたものが10秒で動くようになりました^p^

それ以来vectorはreturnしないことにしました。
って言っても余程データが大きくない限りは影響はほぼないんでしょうが^^;

参照型の引数に結果を上書きするのはあまり書かないです。
関数を呼び出すときに「この関数は引数の値を変えるのか?」というのがわからないからです。(コメント書けばいいじゃんね^p^)
なんで基本的に引数はポインタ型にして、呼び出すときは変数のアドレスを渡しています。

でもnullチェックとかしないといけないからめんどい・~・

25130
記事: 4
登録日時: 7年前

Re: [C++] コンパイラ頼り

投稿記事 by 25130 » 7年前

usao さんが書きました:

CODE:

std::vector && method(~){ ...(略) }
とか書いちゃったことがある人は挙手しましょう.
(^p^)ノ はーい
→(死)
usao さんが書きました: 戻り値はコンパイラが最適化してくれるとかいう話だけど,そこら辺の確実性(?)がよくわからんから

CODE:

//引数のvectorの内容を結果で上書きするよ!
void method( std::vector &rDstResult ){ ... }
とかいうのを書いちゃう.
まぁ、分からなくはないんですけどね…
もう最近のコンパイラ(C++0x規格くらい〜)だといいや ってなりますねー

purin52002 さんが書きました:

CODE:

//vectorとvectorを渡してvectorを返す
vector Func(vector x, vector y) { ... }
これを以下のように書き換えると

CODE:

//vectorの参照とvectorの参照を渡してvectorのポインタに書き込む
void Func(const vector &x, const vector &y, vector *z) { ... }
x,yをconst参照で渡すのは分かりますが、
zはNRVOで殴る(パワーワード)事を前提にreturnでいいのでは(C++0x脳)
purin52002 さんが書きました: 参照型の引数に結果を上書きするのはあまり書かないです。
(省略)
なんで基本的に引数はポインタ型にして、呼び出すときは変数のアドレスを渡しています。
分かります、分かります、
呼び出しの時に裸で渡したのに書き換えられる違和感…

アバター
usao
記事: 1889
登録日時: 12年前

Re: [C++] コンパイラ頼り

投稿記事 by usao » 7年前

> 関数を呼び出すときに「この関数は引数の値を変えるのか?」というのがわからないからです。

変えるかどうかはconstの有無で判断できると思うのですが,どうなんでしょ.
(変えないのならconstではない参照を引数の型にしないだろうし)

というか,ポインタでも一緒の話なのでは…?

アバター
purin52002
記事: 235
登録日時: 8年前

Re: [C++] コンパイラ頼り

投稿記事 by purin52002 » 7年前

CODE:

int a,b;

//第一がconst参照で第二が参照
RefFunc(a, b);//ぱっとみbが書き換えられるかわからない

//第一がconst参照で第二がポインタ
PFunc(a, &b);//bのアドレス渡してる!値が変わるかも?
こういうイメージです^^;

アバター
usao
記事: 1889
登録日時: 12年前

Re: [C++] コンパイラ頼り

投稿記事 by usao » 7年前

> こういうイメージです^^;

関数を呼ぶ(コードを書く)とき,ではなく,関数を呼ぶコードを見たとき,の話ですね.
そういう一貫したルール(?)で書いているという前提があれば,後から読むときに比較的判別し易い,という.

アバター
usao
記事: 1889
登録日時: 12年前

Re: [C++] コンパイラ頼り

投稿記事 by usao » 7年前

本題側については,
・vectorに言うほど大量に要素入れるコード書くのは稀(個人的に)
・コピーが面倒なものは大抵コピーを禁止しちゃう()ので,vectorの要素がポインタとかになってる予感
・vectorをreturnしたいような場面って,速度とか真面目に考えないような場所だったり
 (バッファを使い回すようなことを考えてない場所ってことだ)

…という気がするので,ほとんどの場合,
vectorが無駄にコピーされても(さほど)どうということはない気がします.

25130
記事: 4
登録日時: 7年前

Re: [C++] コンパイラ頼り

投稿記事 by 25130 » 7年前

オフトピック
コードの見た目の話があったので…

初項と公差と生成数を指定して等差数列を生成するメソッドを考えたとき(要らない)
それぞれの定義と呼び出し方法の違いをまとめてみました。

方法1: 初項と公差と生成数と入れ物への参照を渡す

CODE:

// 定義
void Generate(int start, int step, int count, std::vector& rDst);
// 呼び出し
std::vector values;
Generate(5, 10, 200, values);
方法2: 初項と公差と生成数と入れ物へのポインタを渡す

CODE:

// 定義
void Generate(int start, int step, int count, std::vector* pDst);
// 呼び出し
std::vector values;
Generate(5, 10, 200, &values);
方法3: 初項と公差と生成数を渡し、生成されたものを返す

CODE:

// 定義
std::vector Generate(int start, int step, int count);
// 呼び出し
auto values = Generate(5, 10, 200);
最後に編集したユーザー 25130 on 2017年12月14日(木) 21:03 [ 編集 4 回目 ]