回答編集履歴
5
'---'がついたままだった。
answer
CHANGED
@@ -19,7 +19,6 @@
|
|
19
19
|
|
20
20
|
上記の記述にあるように参照が生き残っている間は、テンポラリオブジェクトは破棄されず、使い続ける事が出来ます。C++標準の仕様ですので、**使ってはいけないわけではありません。**ただ、混乱の元になりそうですので、ムーブコンストラクタを実装して、通常のオブジェクトとして変数を確保し、寿命をはっきりさせた方が良いでしょう。
|
21
21
|
|
22
|
-
---
|
23
22
|
###そもそもオブジェクトの破棄とはアクセスできなくなることではない
|
24
23
|
さて、話は変わりますが、テンポラリオブジェクトが破棄されると言っても、テンポラリオブジェクトによって使われていたスタック上のメモリ領域が0埋めされるとか、該当メモリ領域へのアクセスが拒否が起きるとか、そういうことではありません。スタック上に確保されたメモリ領域は、他に再利用されない限りそのままであり、**無理矢理使用することは可能です**。しかし、言語の仕様上、その領域がいつまでそのままになっているかは一切保証がありません。つまり、**このメモリ領域はもう使う予定は無いから再利用してもいいよ**というのが、寿命がつきて**破棄**されるということです。もし、破棄された後とその利用の間に何か別の処理を追加してあった場合、それだけでテンポラリオブジェクトに使っていたスタック上のメモリ領域が上書きされ、おかしな事が起きる可能性があります。これは、関数が終わった後に破棄されたローカル変数や、deleteやfreeでのメモリ解放でも同じ事が言えます。
|
25
24
|
|
4
constの左辺値参照を追加し、整理しました。
answer
CHANGED
@@ -1,37 +1,51 @@
|
|
1
|
+
###Visual Studioの言語拡張でした
|
1
2
|
Visual Studioで動作を確認しました。どうやら、最初に思っていたのと違ったようです。
|
2
3
|
|
3
|
-
問題なく動作するのは**Visual Studioの言語拡張**であり、標準のC++としては**違反**になります。"/W4"で警告レベルを上げると警告が表示され、"/Za"で言語拡張を無効化するとエラーになります。
|
4
|
-
[Temporary Objects Can be Bound to Non-Const References | Microsoft Connect](https://connect.microsoft.com/VisualStudio/feedback/details/807118/temporary-objects-can-be-bound-to-non-const-references)
|
5
|
-
[c++ - Non-const reference bound to temporary, Visual Studio bug? - Stack Overflow](http://stackoverflow.com/questions/16380966/non-const-reference-bound-to-temporary-visual-studio-bug)
|
6
|
-
[c++ - Visual Studio is not creating temporary object when typecasting? - Stack Overflow](http://stackoverflow.com/questions/28402173/visual-studio-is-not-creating-temporary-object-when-typecasting)
|
7
|
-
[コンパイラの警告 (レベル 4) C4239](https://msdn.microsoft.com/ja-jp/library/186yxbac.aspx)
|
4
|
+
問題なく動作するのは**Visual Studioの言語拡張**であり、標準のC++としては**違反**になります。"/W4"で警告レベルを上げると警告が表示され、"/Za"で言語拡張を無効化するとエラーになります。下記を参考にして下さい。(拡張としては、constありと同じように寿命が延びるようになるようです。constありの場合の話は後述。)
|
8
5
|
|
9
|
-
|
6
|
+
* [Temporary Objects Can be Bound to Non-Const References | Microsoft Connect](https://connect.microsoft.com/VisualStudio/feedback/details/807118/temporary-objects-can-be-bound-to-non-const-references)
|
7
|
+
* [c++ - Non-const reference bound to temporary, Visual Studio bug? - Stack Overflow](http://stackoverflow.com/questions/16380966/non-const-reference-bound-to-temporary-visual-studio-bug)
|
8
|
+
* [c++ - Visual Studio is not creating temporary object when typecasting? - Stack Overflow](http://stackoverflow.com/questions/28402173/visual-studio-is-not-creating-temporary-object-when-typecasting)
|
9
|
+
* [コンパイラの警告 (レベル 4) C4239](https://msdn.microsoft.com/ja-jp/library/186yxbac.aspx)
|
10
10
|
|
11
|
-
|
11
|
+
C++標準ではないVisual Studio特有の仕様ですので、Visual Studioを**永遠に使い続ける**のであれば問題ありません。他のコンパイラでも動作できるように移植する予定であれば、このような記述は避けるべきでしょう。このままではClangやGCCではエラーになってコンパイルできません。
|
12
12
|
|
13
|
+
###constな左辺値参照はテンポラリオブジェクトの寿命を延ばす
|
14
|
+
`const CBase& base = CBase();`とconstがついている場合は(メンバー関数もconstにする必要がありますが)、参照が存在する間だけオブジェクトの寿命が延びるため、標準のC++として**問題ありません**。これは式が終了しても、テンポラリオブジェクトが破棄されない例外の一つです。
|
15
|
+
|
16
|
+
参考: [Object lifetime - cppreference.com](http://en.cppreference.com/w/cpp/language/lifetime#Temporary_object_lifetime)
|
17
|
+
> The lifetime of a temporary object may be extended by binding to a const lvalue reference __or to an rvalue reference (since C++11)__, see [reference initialization](http://en.cppreference.com/w/cpp/language/reference_initialization#Lifetime_of_a_temporary) for details.
|
18
|
+
> constな左辺値参照__または右辺値参照(C++11から)__に紐付けられる場合、テンポラリオブジェクトの寿命は延長され得る。詳しくは[参照の初期化](http://en.cppreference.com/w/cpp/language/reference_initialization#Lifetime_of_a_temporary)を見よ。
|
19
|
+
|
20
|
+
上記の記述にあるように参照が生き残っている間は、テンポラリオブジェクトは破棄されず、使い続ける事が出来ます。C++標準の仕様ですので、**使ってはいけないわけではありません。**ただ、混乱の元になりそうですので、ムーブコンストラクタを実装して、通常のオブジェクトとして変数を確保し、寿命をはっきりさせた方が良いでしょう。
|
21
|
+
|
13
22
|
---
|
14
|
-
|
15
|
-
|
23
|
+
###そもそもオブジェクトの破棄とはアクセスできなくなることではない
|
24
|
+
さて、話は変わりますが、テンポラリオブジェクトが破棄されると言っても、テンポラリオブジェクトによって使われていたスタック上のメモリ領域が0埋めされるとか、該当メモリ領域へのアクセスが拒否が起きるとか、そういうことではありません。スタック上に確保されたメモリ領域は、他に再利用されない限りそのままであり、**無理矢理使用することは可能です**。しかし、言語の仕様上、その領域がいつまでそのままになっているかは一切保証がありません。つまり、**このメモリ領域はもう使う予定は無いから再利用してもいいよ**というのが、寿命がつきて**破棄**されるということです。もし、破棄された後とその利用の間に何か別の処理を追加してあった場合、それだけでテンポラリオブジェクトに使っていたスタック上のメモリ領域が上書きされ、おかしな事が起きる可能性があります。これは、関数が終わった後に破棄されたローカル変数や、deleteやfreeでのメモリ解放でも同じ事が言えます。
|
16
25
|
|
17
|
-
さて、テンポラリオブジェクトが破棄されると言っても、テンポラリオブジェクトによって使われていたスタック上のメモリ領域が0埋めされるとか、そういうことではありません。スタック上に確保されたメモリ領域は、他に再利用されない限りそのままであり、**無理矢理使用することは可能です**。しかし、言語の仕様上、その領域がいつまでそのままになっているかは一切保証がありません。つまり、**このメモリ領域はもう使う予定は無いから再利用してもいいよ**というのが、**破棄**です。例えば、`base.Show();`の前に何か処理を追加してみて下さい。それだけでテンポラリオブジェクトに使っていたスタック上のメモリ領域が上書きされ、おかしな事が起きる可能性があります。これは、関数が終わった後に破棄されたローカル変数や、deleteやfreeでのメモリ解放でも同じ事が言えます。
|
18
|
-
|
19
26
|
なお、コンパイラの最適化もあるため、実際上書きされるようなコードになるかはわかりません。逆に、間に処理が無くても、最適化によって、上書きされるようなコードが挿入される場合があります。また、デバッグ機能を使っているときは、バグ出しのためにそのような上書きコードが随時挟まれる場合があります。どうなるかはコンパイラやその時のオプション次第です。
|
20
27
|
|
21
|
-
参考: deleteしても使えてしまう例。こ
|
28
|
+
参考: deleteしても使えてしまう例。何が起こるかはコンパイラやオプションによって異なります。
|
22
29
|
```C++
|
23
30
|
#include <iostream>
|
31
|
+
#include <string>
|
24
32
|
|
25
33
|
class CBase {
|
34
|
+
private:
|
35
|
+
std::string show;
|
26
36
|
public:
|
37
|
+
CBase() {
|
38
|
+
show = "Show";
|
39
|
+
};
|
27
40
|
void Show() {
|
28
|
-
std::cout <<
|
41
|
+
std::cout << show << std::endl;
|
29
42
|
}
|
30
43
|
};
|
31
44
|
|
32
45
|
int main() {
|
33
|
-
|
46
|
+
auto base = new CBase();
|
34
47
|
delete base;
|
48
|
+
auto pstr = new std::string("None");
|
35
49
|
base->Show();
|
36
50
|
}
|
37
51
|
```
|
3
ちゃんと調べたら、VSの言語拡張でした。
answer
CHANGED
@@ -1,3 +1,17 @@
|
|
1
|
+
Visual Studioで動作を確認しました。どうやら、最初に思っていたのと違ったようです。
|
2
|
+
|
3
|
+
問題なく動作するのは**Visual Studioの言語拡張**であり、標準のC++としては**違反**になります。"/W4"で警告レベルを上げると警告が表示され、"/Za"で言語拡張を無効化するとエラーになります。
|
4
|
+
[Temporary Objects Can be Bound to Non-Const References | Microsoft Connect](https://connect.microsoft.com/VisualStudio/feedback/details/807118/temporary-objects-can-be-bound-to-non-const-references)
|
5
|
+
[c++ - Non-const reference bound to temporary, Visual Studio bug? - Stack Overflow](http://stackoverflow.com/questions/16380966/non-const-reference-bound-to-temporary-visual-studio-bug)
|
6
|
+
[c++ - Visual Studio is not creating temporary object when typecasting? - Stack Overflow](http://stackoverflow.com/questions/28402173/visual-studio-is-not-creating-temporary-object-when-typecasting)
|
7
|
+
[コンパイラの警告 (レベル 4) C4239](https://msdn.microsoft.com/ja-jp/library/186yxbac.aspx)
|
8
|
+
|
9
|
+
C++標準ではないVisual Studio特有の仕様ですので、Visual Studioを**永遠に使い続ける**のであれば問題ありません。他のコンパイラでも動作できるように移植する予定であれば、そのような記述は避けるべきでしょう。
|
10
|
+
|
11
|
+
修正前の下の話は、今回の話ではそうとは言えないので、一般的な話だと思って下さい。
|
12
|
+
|
13
|
+
---
|
14
|
+
【修正前】
|
1
15
|
Clang 700.1.81とGCC 5.3.0ではエラーになってコンパイルできませんね。
|
2
16
|
|
3
17
|
さて、テンポラリオブジェクトが破棄されると言っても、テンポラリオブジェクトによって使われていたスタック上のメモリ領域が0埋めされるとか、そういうことではありません。スタック上に確保されたメモリ領域は、他に再利用されない限りそのままであり、**無理矢理使用することは可能です**。しかし、言語の仕様上、その領域がいつまでそのままになっているかは一切保証がありません。つまり、**このメモリ領域はもう使う予定は無いから再利用してもいいよ**というのが、**破棄**です。例えば、`base.Show();`の前に何か処理を追加してみて下さい。それだけでテンポラリオブジェクトに使っていたスタック上のメモリ領域が上書きされ、おかしな事が起きる可能性があります。これは、関数が終わった後に破棄されたローカル変数や、deleteやfreeでのメモリ解放でも同じ事が言えます。
|
2
日本語の修正
answer
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
Clang 700.1.81とGCC 5.3.0ではエラーになってコンパイルできませんね。
|
2
2
|
|
3
|
-
さて、テンポラリオブジェクトが破棄されると言っても、テンポラリオブジェクトによって使われていたスタック上のメモリ領域が0埋めされるとか、そういうことではありません。スタック上に確保されたメモリ領域は、他に再利用されない限りそのままであり、**無理矢理使用することは可能です**。しかし、言語の仕様上、その領域がいつまでそのままになっているかは一切保証がありません。つまり、**このメモリ領域はもう使う予定は無いから再利用してもいいよ**というのが、**破棄**です。例えば、`base.Show();`の前に何か処理を追加してみて下さい。それだけでテンポラリオブジェクトに使っていたスタック上のメモリ領域が上書きされ、おかしな事が起きる可能性があります。これは、関数が終わった後
|
3
|
+
さて、テンポラリオブジェクトが破棄されると言っても、テンポラリオブジェクトによって使われていたスタック上のメモリ領域が0埋めされるとか、そういうことではありません。スタック上に確保されたメモリ領域は、他に再利用されない限りそのままであり、**無理矢理使用することは可能です**。しかし、言語の仕様上、その領域がいつまでそのままになっているかは一切保証がありません。つまり、**このメモリ領域はもう使う予定は無いから再利用してもいいよ**というのが、**破棄**です。例えば、`base.Show();`の前に何か処理を追加してみて下さい。それだけでテンポラリオブジェクトに使っていたスタック上のメモリ領域が上書きされ、おかしな事が起きる可能性があります。これは、関数が終わった後に破棄されたローカル変数や、deleteやfreeでのメモリ解放でも同じ事が言えます。
|
4
4
|
|
5
5
|
なお、コンパイラの最適化もあるため、実際上書きされるようなコードになるかはわかりません。逆に、間に処理が無くても、最適化によって、上書きされるようなコードが挿入される場合があります。また、デバッグ機能を使っているときは、バグ出しのためにそのような上書きコードが随時挟まれる場合があります。どうなるかはコンパイラやその時のオプション次第です。
|
6
6
|
|
7
|
-
参考:
|
7
|
+
参考: deleteしても使えてしまう例。こっちはClang/GCCでもコンパイルできてしまいます。
|
8
8
|
```C++
|
9
9
|
#include <iostream>
|
10
10
|
|
1
C\+\+\+じゃなくてC\+\+でしょ
answer
CHANGED
@@ -5,7 +5,7 @@
|
|
5
5
|
なお、コンパイラの最適化もあるため、実際上書きされるようなコードになるかはわかりません。逆に、間に処理が無くても、最適化によって、上書きされるようなコードが挿入される場合があります。また、デバッグ機能を使っているときは、バグ出しのためにそのような上書きコードが随時挟まれる場合があります。どうなるかはコンパイラやその時のオプション次第です。
|
6
6
|
|
7
7
|
参考: deletしても使えてしまう例。こっちはClang/GCCでもコンパイルできてしまいます。
|
8
|
-
```C++
|
8
|
+
```C++
|
9
9
|
#include <iostream>
|
10
10
|
|
11
11
|
class CBase {
|