関数の返値の有効範囲について

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
アバター
MoNoQLoREATOR
記事: 284
登録日時: 13年前
住所: 東京

関数の返値の有効範囲について

#1

投稿記事 by MoNoQLoREATOR » 12年前

関数の返り値の有効範囲はどこまでなのでしょうか?

まず、この疑問は次の仮定が誤っていないことを前提としています。
仮定:
ポインタや参照ではなく実体を返す関数が返値を返すと、その分のメモリ領域が確保され、一旦そこにデータが保存される

単純に考えると、 } まででしょうか?
それとも、その行の終わりまで来ると消滅してしまうのでしょうか。
はたまた、それを関数の引数に渡した場合は・・・?


ご教授よろしくお願いいたします。

box
記事: 2002
登録日時: 13年前

Re: 関数の返値の有効範囲について

#2

投稿記事 by box » 12年前

MoNoQLoREATOR さんが書きました: 単純に考えると、 } まででしょうか?
どういうコードを想定されていますか?
MoNoQLoREATOR さんが書きました: それとも、その行の終わりまで来ると消滅してしまうのでしょうか。
どういうコードを想定されていますか?
MoNoQLoREATOR さんが書きました: はたまた、それを関数の引数に渡した場合は・・・?
どういうコードを想定されていますか?
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

beatle
記事: 1281
登録日時: 12年前
住所: 埼玉
連絡を取る:

Re: 関数の返値の有効範囲について

#3

投稿記事 by beatle » 12年前

その文の終わりまで、だったと思います。

box
記事: 2002
登録日時: 13年前

Re: 関数の返値の有効範囲について

#4

投稿記事 by box » 12年前

beatle さんが書きました:その文の終わりまで、だったと思います。
具体例を書いてみていただけないでしょうか。
「その文」というのが何を指すのか、今ひとつピンと来ないものでして。
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

ISLe
記事: 2650
登録日時: 13年前
連絡を取る:

Re: 関数の返値の有効範囲について

#5

投稿記事 by ISLe » 12年前

『一時オブジェクト』を調べてみてください。

一時オブジェクトの生存期間は完結式の終わりまでです。
いくつか例外がありますが関数の戻り値はそこに含まれません。

アバター
MoNoQLoREATOR
記事: 284
登録日時: 13年前
住所: 東京

Re: 関数の返値の有効範囲について

#6

投稿記事 by MoNoQLoREATOR » 12年前

コード:

#include <string>

string getstr(){
	string output;
	return output;
}

int main(){
	const char *str = getstr().c_str();
	printf(str);
}
このようなコードを想定していたのですが、「一時オブジェクト」で検索してみた結果これは不正アクセスになります・・・よね?
string型で拾って内容をコピーさせるしかなさそうですね。

ありがとうございました。

アバター
GRAM
記事: 164
登録日時: 13年前
住所: 大阪

Re: 関数の返値の有効範囲について

#7

投稿記事 by GRAM » 12年前

仮にstringで拾ったとしても、文字列の内容がコピーされることはないのではないかと思います。
string内部には普通参照カウントがありますので、(そして一時オブジェクトが破棄される前に変更されることもないので)
コピーは浅く行われると予想できます。(予想ですが・・・)
ということでオーバーヘッドは大したことないのではないかと。

追記:
確かにこの場合はNRVOが適応されますね。失礼しました。
自分の話は仮に関数がもっと複雑で、複数のreturn文で異なる名前のインスタンスを返したとしてもと受け取ってください・・・。
最後に編集したユーザー GRAM on 2011年11月10日(木) 01:55 [ 編集 1 回目 ]

アバター
tk-xleader
記事: 158
登録日時: 13年前
連絡を取る:

Re: 関数の返値の有効範囲について

#8

投稿記事 by tk-xleader » 12年前

「NRVO」や「戻り値最適化」あたりで検索してもらえればより分かりやすい情報が得られると思いますが…
getstr 関数の戻り値はどうせ捨てられる値なので、コピーするよりもムーブしたほうが無駄がありません。C++03でも、この最適化は行われます。
ですから、コピーのコストについては、そこまで問題ではないかと思います。

beatle
記事: 1281
登録日時: 12年前
住所: 埼玉
連絡を取る:

Re: 関数の返値の有効範囲について

#9

投稿記事 by beatle » 12年前

GRAM さんが書きました:仮にstringで拾ったとしても、文字列の内容がコピーされることはないのではないかと思います。
string内部には普通参照カウントがありますので、(そして一時オブジェクトが破棄される前に変更されることもないので)
コピーは浅く行われると予想できます。(予想ですが・・・)
ということでオーバーヘッドは大したことないのではないかと。
C++11ではstd::basic_stringを参照カウントで実装するのは禁止(というより実質的に不可能)になりました。

beatle
記事: 1281
登録日時: 12年前
住所: 埼玉
連絡を取る:

Re: 関数の返値の有効範囲について

#10

投稿記事 by beatle » 12年前

box さんが書きました:
beatle さんが書きました:その文の終わりまで、だったと思います。
具体例を書いてみていただけないでしょうか。
「その文」というのが何を指すのか、今ひとつピンと来ないものでして。
僕も少し勘違いしていました。ISLeさんのいうとおり、完結式(full-expression)の終わりまで、のようですね。
ちなみに、「その文」というのは、関数呼び出しを含む文、という意味で使いました。

以下、規格などを調べつつ書いてみました。

コード:

const char* str;
str = getstr().c_str(); // 式1;
printf(str);
式1は他の式の部分式ではないため完結式です。
したがって、strへの代入が終了した時点で完結式が終わり、getstr()の戻り値(一時オブジェクト)のデストラクタが呼ばれます。
もちろんprintf(str)は不正なアクセスです。

一方で

コード:

const char* str;
str = getstr().c_str(), printf(str); // 式2;
の場合、式2は「式3, 式4」という形になっています。
一時オブジェクトを生成する式3は式2の部分式ですから完結式ではなく、式2が完結式です。
カンマ演算子で繋がれた式は左から右に評価されますから、式4が終了すれば式2が終了します。
したがって、式4、つまりprintf(str)を実行後、getstr()の戻り値(一時オブジェクト)のデストラクタが呼ばれます。
printf(str)は不正なアクセスにはなりません。

閉鎖

“C言語何でも質問掲示板” へ戻る