デストラクタが呼ばれるタイミングが複雑だから
そこら辺の事が載ってるサイトを教えて欲しい
class TEST{
public:
TEST(){}
~TEST(){
std::cout << "oppai\n";
}
};
TEST unchi(){
TEST chinko;
return chinko;
}
int main(){
TEST t=unchi();
std::cout << "manko\n";
return 0;
}
このプログラムで、unchi関数が終わった時点でスタックからchinkoが消されるから、
chinkoのデストラクタが呼ばれると思ったんだけど、どうもそうならないみたいで何故か分からん
つまり俺の予想だと
oppai→manko→oppai
の順で表示されると思ったんだけど実際は
manko→oppai
になってる……
文字列やコンストラクタ名で
教えるのが嫌なになった
教えない
実体を返してるからデストラクタは呼ばれないんじゃなかろうか
逆にoppai→manko→oppaiだと思った理由は何なの
なるほどなるほど、ローカル変数かー確かに〜でもmainで実体コピーされるよね?
もしかして最適化かな…?
最適化のせいでunchi関数がmainの中に組み込まれてるんじゃないか…?(´・ω・`)
でもそれでデストラクタが呼ばれないってことがあるのだろうか…
うーむ…まぁ動けばいいんだけどさ
原因を分からないままにするのって気持ち悪いよね…
19以下、5ちゃんねるからVIPがお送りします2020/06/26(金) 20:41:36.266
本題とは関係ないけど、TEST t {unchi()}; って書いて
結果見る限りインライン展開されてそう
最適化切ってコンパイルしてみたら
最適化のせいだったらうそついたごめん そうかもしれない あーでも忘れた
chinkoどこで表示されるんだ?と思って実行してみたけどやっぱりchinkoは表示されない
コピペミス?
デストラクタ以前に
std::cout << "chinko\n";
がどこにもないのにどうやって表示されるんだ
28以下、5ちゃんねるからVIPがお送りします2020/06/26(金) 20:50:04.128
古いコンパイラは一度unchi()を呼び出して、返値を一時変数によっこして
戻ってきてそれからtへ代入していた
この一手間があほくさいってんで直接元のところ(t)に代入するように直せよという議論があって実装された歴史の経緯がある
俺の妄想だが
最適化オフにしてコンパイルしてみたけど結果は変わらず…
やはり仕様なのか…?(´・ω・`)
起こっているのはNRVOと呼ばれる言語仕様レベルで許可された最適化なので、
もしかしたらコンパイラオプションとは無関係に発生するのかもしれない
やっぱそうっぽい
-fno-elide-constructors オプションをつけるとNRVOを無効化できるらしい
ちなみにNRVO、「許可された」であって「必ず省略されるとは限らない」ってことに注意な
似たような機能に変数を使わず return TEST(); とするRVOってのがあるが、
こっちはC++17で「必ず省略する」という仕様になった
おお!!表示がoppai→oppai→manko→oppaiになったぞ!!
想定よりoppaiがひとつ多いのは、リターン時に使った領域とtの領域とchinkoの領域がそれぞれ異なるからだろうな
まぁこの件はこれで解決なんだけど(´・ω・`)
俺はC言語は流暢に使えるんだがC++はぎこちなくてな
typedef struct{
int length;
Element* arr;
} Elements;
こんな感じの構造体をC++で書くと
class Elements{
public:
int length;
Element* arr;
Elements():length(0),arr(NULL){}
~Elements(){ if(arr)delete[] arr; }
};
とまぁこんな感じになる(´・ω・`)
ある関数でElements型の変数を返したいときに、
C言語だとarrはちゃんとコピーされるわけだが
C++(下の書き方)だとreturnした直後にデストラクタで
arrがdeleteされてしまうという問題がある…
どう解決したらいいだろう?