🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

1回答

3351閲覧

std::vector<>.push_back()をする時のコピーコンストラクタ。デストラクタ。コンストラクタはどのような仕組みで起こってるのか知りたい。

退会済みユーザー

退会済みユーザー

総合スコア0

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2021/01/27 07:05

提示コードですがmain関数の処理をすると提示画像のような結果になるのですがこの3つの処理がなぜどのような理由で起こっているのか知りたいです。一時オブジェクトを生成するのでまずコンストラクタが起きてその次にコピーするのでコピーコンストラクタもわかります
その後の2つのデストラクタの順序とその理由が知りたいです。

イメージ説明

cpp

1#include "stdio.h" 2#include "glm/glm.hpp" 3#include <array> 4#include <vector> 5#include <iostream> 6#include "conio.h" 7 8using namespace std; 9 10class test { 11public: 12 test(int a) 13 { 14 15 } 16}; 17 18class Bullet { 19public: 20 21 //コンストラクタ 22 Bullet(int r) { 23 a = new test(3); 24 printf("コンストラクタ\n"); 25 } 26 27 //デストラクタ 28 ~Bullet() { 29 delete a; 30 a = nullptr; 31 printf("--- デストラクタ\n"); 32 } 33 34 //コピーコンストラクタ 35 Bullet(const Bullet& obj) 36 { 37 printf("コピーコンストラクタ\n"); 38 a = new test(3); 39 } 40 41private: 42 43 test* a; 44 45}; 46 47 48int main() 49{ 50 51 std::vector<Bullet> bullet; 52 bullet.push_back(Bullet(4)); 53 54 55 56 return 0; 57}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2021/01/27 07:22

すいませんでした。
episteme

2021/01/27 08:05

なにが問題なのかわからない。 「コンストラクタがふたつ動いたから、デストラクタもふたつ動いた」のどこに疑問があるのでしょうか。
退会済みユーザー

退会済みユーザー

2021/01/27 08:06

なるほど
episteme

2021/01/27 08:32

"なるほど"じゃネーヨ。なにが疑問/問題なんです?
退会済みユーザー

退会済みユーザー

2021/01/27 08:34

どうしてデストラクタが二回なのか合って思ったんですけどそれ聞いてすっきりしました。
FKD

2021/01/27 09:13 編集

一時オブジェクト?は、使用箇所のスコープのローカル変数として実装されている事が多い[要出典]ので、スコープ抜けるタイミングでデストラクタが動きますよ。 この場合のスコープは、push_back()なのか、main{}なのかは分かりませんが、 確認したければデバッガでトレース実行してみてください。
maisumakun

2021/01/27 10:37

> 一時オブジェクト?は、使用箇所のスコープのローカル変数として実装されている事が多い[要出典]ので、 いえ、一時オブジェクトの寿命はその式の中だけです。次の行に進む前にデストラクタが走ります。
episteme

2021/01/27 14:07

> ...それ聞いてすっきりしました。 解決したのなら、適切に close してください。
guest

回答1

0

ベストアンサー

printfを仕込むことで動作を見ることを行っているのであれば,
中途半端にやるんじゃなくて,例えばこのくらい仕込んで見れば,少しはわかるんじゃないですかね.

C++

1//変更点(1) 2//観測したい現象に何も関係のない class test は取っ払ったぞ 3 4 5//変更点(2) 6//インスタンス毎に異なる MyNumber の値を持ち, 7//コンストラクタとデストラクタでその値を表示するようにしたぞ 8class Bullet { 9public: 10 //コンストラクタ 11 Bullet(int r) { 12 MyNumber = ++Counter; 13 printf("コンストラクタ %d\n", MyNumber); 14 } 15 16 //デストラクタ 17 ~Bullet() { 18 printf("--- デストラクタ %d\n", MyNumber); 19 } 20 21 //コピーコンストラクタ 22 Bullet(const Bullet& obj) 23 { 24 MyNumber = ++Counter; 25 printf("コピーコンストラクタ %d\n", MyNumber); 26 } 27 28private: 29 int MyNumber; 30 static int Counter; //MyNumber生成用 31}; 32 33int Bullet::Counter = 0; 34 35//変更点(3) 36//無駄とも思えるくらいに各タイミングにprintfを書いてみたぞ. 37//オブジェクトの生存期間に関する事柄を観測しやすいようにスコープも追加したぞ. 38int main() 39{ 40 printf( "テスト用のスコープに入るぞ\n" ); 41 { 42 printf( "テスト用のスコープに入ったぞ\n" ); 43 44 std::vector<Bullet> bullet; 45 printf( "vector<Buller> bullet を構築したぞ\n" ); 46 47 printf( "push_back作業スコープに入るぞ\n" ); 48 { 49 printf( "push_back作業スコープに入ったんでpush_backするぞ\n" ); 50 bullet.push_back(Bullet(4)); 51 printf( "push_backしたぞ\n" ); 52 printf( "push_back作業スコープ抜けるぞ\n" ); 53 } 54 printf( "push_back作業スコープ抜けたぞ\n" ); 55 56 printf( "テスト用のスコープを抜けるぞ\n" ); 57 } 58 printf( "テスト用のスコープを抜けたぞ\n" ); 59 printf( "main()のreturn直前だぞ\n" ); 60 return 0; 61}

[追記]結果も載せておく.

2つのデストラクタの順序とその理由が知りたいです。

こんだけ表示を仕込めば,動作結果見ればまぁ想像つきますよね.

Text

1テスト用のスコープに入るぞ 2テスト用のスコープに入ったぞ 3vector<Buller> bullet を構築したぞ 4push_back作業スコープに入るぞ 5push_back作業スコープに入ったんでpush_backするぞ 6コンストラクタ 1 7コピーコンストラクタ 2 8--- デストラクタ 1 9push_backしたぞ 10push_back作業スコープ抜けるぞ 11push_back作業スコープ抜けたぞ 12テスト用のスコープを抜けるぞ 13--- デストラクタ 2 14テスト用のスコープを抜けたぞ 15main()のreturn直前だぞ

投稿2021/01/28 01:52

編集2021/01/28 02:00
fana

総合スコア11990

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

fana

2021/01/28 02:18 編集

"push_back作業スコープ" を(わざわざ)設けることで, 「質問への追記・修正、ベストアンサー選択の依頼」欄にて述べられている 一時オブジェクトの寿命の話 も観測できるようにしてありますぞ. --- デストラクタ 1 push_backしたぞ push_back作業スコープ抜けるぞ push_back作業スコープ抜けたぞ という表示順から, > いえ、一時オブジェクトの寿命はその式の中だけです。次の行に進む前にデストラクタが走ります。 を見ることができますな.
FKD

2021/01/28 04:57

> maisumakunさん、fanaさん オブジェクトの寿命に関して、しっかり確認できて助かります。 名前なしの変数でも、式単位でしっかりとデストラクタ走るのですね。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問