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

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

詳細はこちら
C++

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

Q&A

解決済

3回答

1356閲覧

動的確保したメモリを開放したあとの挙動がわからない。

yoshiki_iwasa

総合スコア23

C++

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

0グッド

0クリップ

投稿2020/12/03 03:08

new で作成した2種類の派生クラスをdeleteしたあとの挙動について。

質問は、

ある基底クラス(BASE)を継承した派生クラスA,B(親は共通)のインスタンスを作成した後、Aだけをdelete したら、依然としてAに対して参照できBASEの値も残るのに、Bも削除したらAの基底クラスである BASEの値を参照できなくなるのはなぜか

です。

すいませんわかりにくいですよね(^^ ;) したのサンプルコードと実行例を見ていいただくとわかると思います。
OS は MacOS Catalina です

###サンプルコード
基底クラスBase を継承したクラス、Hasei_1 と Hasei_2 を作成します

C++

1////Base.cpp 2 3#include <string> 4#include <iostream> 5 6class Base 7{ 8 private: 9 std::string name; 10 public: 11 Base(std::string); 12 std::string getName(); 13 virtual ~Base(); 14}; 15 16Base::Base(std::string name) 17{ 18 this->name = name; 19} 20 21Base::~Base() 22{ 23} 24 25std::string Base::getName() 26{ 27 return (this->name); 28} 29 30/* 31 派生クラス1の作成 32*/ 33class Hasei_1 : public Base 34{ 35 private: 36 /* data */ 37 public: 38 Hasei_1(); 39 ~Hasei_1(); 40 41}; 42 43Hasei_1::Hasei_1() : Base("Hasei_1") 44{ 45} 46 47Hasei_1::~Hasei_1() 48{ 49} 50 51 52/* 53 派生クラス2の作成 54*/ 55 56 57class Hasei_2 : public Base 58{ 59 private: 60 /* data */ 61 public: 62 Hasei_2(); 63 ~Hasei_2(); 64}; 65 66 67Hasei_2::Hasei_2() : Base("Hasei_2") 68{ 69} 70 71Hasei_2::~Hasei_2() 72{ 73} 74 75/* 76<< のオーバーロード 77*/ 78 79std::ostream &operator<<(std::ostream &os, Base &obj) 80{ 81 os << "Name is " << obj.getName() << std::endl; 82 return (os); 83} 84 85/* 86 main 関数 87*/ 88 89int main() 90{ 91 Base *hasei_1 = new Hasei_1; 92 Base *hasei_2 = new Hasei_2; 93 std::cout << "\n\n派生クラスの参照をしてみる\n" << std::endl; 94 std::cout << *hasei_1 << std::endl; 95 std::cout << *hasei_2 << std::endl; 96 97 delete hasei_1; 98 std::cout << "\n\n\"delete hasei_1\" の後にhasei_1を参照をしてみる\n" << std::endl; 99 100 std::cout << *hasei_1 << std::endl; 101 std::cout << "↑ まだname が残っている\n" << std::endl; 102 103 delete hasei_2; 104 std::cout << "\n\n\"delete hasei_2\" の後にhasei_1を参照をしてみる\n" << std::endl; 105 106 std::cout << *hasei_1 << std::endl; 107 std::cout << "↑ もうname が消えている\n" << std::endl; 108 109 std::cout << *hasei_2 << std::endl; 110 std::cout << "↑ hasei_2 は残ってる\n" << std::endl; 111 112 113} 114

###実行結果

Shell

1> clang++ Base.cpp 2> ./a.out 3 4 5派生クラスの参照をしてみる 6 7Name is Hasei_1 8 9Name is Hasei_2 10 11 12 13"delete hasei_1" の後にhasei_1を参照をしてみる 14 15Name is Hasei_1 16 17↑ まだname が残っている 18 19 20 21"delete hasei_2" の後にhasei_1を参照をしてみる 22 23Name is 24 25↑ もうname が消えている 26 27Name is Hasei_2 28 29↑ hasei_2 は残ってる 30

同じクラスを継承した2つのオブジェクトの片方をdelete するだけでは、deleteされた基底クラスの値は失われないのに、両方削除すると、先に削除したほうの基底クラスの値が失われるのはなぜでしょうか....?

質問クリアでしょうか?よろしくお願いします。

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

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

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

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

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

guest

回答3

0

同じクラスを継承した2つのオブジェクトの片方をdelete するだけでは、deleteされた基底クラスの値は失われないのに、両方削除すると、先に削除したほうの基底クラスの値が失われるのはなぜでしょうか....?

考えること自体が無意味です。deleteしたあとのポインタを参照した際の挙動は、何も保証されていません

投稿2020/12/03 03:12

maisumakun

総合スコア145971

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

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

maisumakun

2020/12/03 03:24 編集

解放後のポインタを使った参照は、その場でクラッシュしたり、ぜんぜん違う箇所のメモリを書き換えるような意味不明な動作をしたりしたとしても文句が言えないものです。
yoshiki_iwasa

2020/12/06 06:25

お返事おそくなってすいません。 回答ありがとうございます! なるほど、解放後のメモリにアクセスしたときの挙動は未定義で、そこを考えてもしかたがないのですね... ありがとうございました!!!
guest

0

ベストアンサー

言語仕様から関連する箇所を探しました。

C++ で未定義の部分について処理系 (や実行環境) の仕様として明文化されていない限り、その挙動は信頼できません。

解放後のメモリが再利用されるまでの間はデータの残骸が残っていて意味ありげな挙動をするかもしれませんし、厳格なメモリ管理をする環境では OS が不正なアクセスを検出してエラーを出すかもしれませんし、暴走してどうにもならなくなるかもしれません。

未定義の挙動がどうなるかを考えるべきではなく事実上禁止されていると考えてください。

投稿2020/12/03 07:58

SaitoAtsushi

総合スコア5684

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

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

yoshiki_iwasa

2020/12/06 06:28

回答ありがとうございます!! なるほどです。やっぱり、不正なメモリアクセスによる挙動は未定義なんですね リンクなどをあわせた詳しいご回答ありがとうございました!!
guest

0

Aだけをdelete したら、依然としてAに対して参照できBASEの値も残るのに

というのが大きな間違いです
参照できる、というのはたまたまそうなっただけで、アクセス違反です。
C/C++の言語においては実行時のエラーを検出しません。

投稿2020/12/03 04:04

編集2020/12/03 04:05
y_waiwai

総合スコア88038

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

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

yoshiki_iwasa

2020/12/06 06:26

遅くなってすみません! アクセス違反をしたときの挙動は未定義なんですね... ありがとうございます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問