質問をすることでしか得られない、回答やアドバイスがある。

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

新規登録して質問してみよう
ただいま回答率
85.48%
C++

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

Q&A

解決済

2回答

3498閲覧

C++ コピーコンストラクタの使用方法

saito.kaz

総合スコア76

C++

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

0グッド

0クリップ

投稿2016/01/21 05:12

編集2016/01/21 05:29

###前提・実現したいこと
showdataに値渡しが行われた際に、デストラクタが発生するのを防ぐために、コピーコンストラクタを実装しましたが、エラーが発生し解決できません。
エラー箇所を解決できないので、すいませんが教えてください。

###発生している問題・エラーメッセージ
エラー文は下記のものだけです。
Runtime error(Exit status:134(Abort signal from abort(3)))
###ソースコード

<ヘッダー文> class Worker{ public: int number; char* name; double salary; Worker(); Worker(const Worker &obj); ~Worker(); }; <メイン文> #include <iostream> #include "Worker.h" using namespace std; Worker::Worker(){ name = new char[80]; cout<< " This is Constructor " << "\n"; strcpy(name, "undifined"); number = 0; salary = 0; } Worker::Worker(const Worker &obj){ cout<< " This is Copy Constructor " << "\n"; name = new char[80]; name = obj.name; this->number = obj.number; this->salary = obj.salary; }; Worker::~Worker(){ delete[] name; cout << "デコンストラクタ" << "\n"; } void ShowData(Worker w2){ cout << "name = " << w2.name << "\n"; strcpy(w2.name,"AVD"); cout << "name = " << w2.name << "\n"; cout << "number = " << w2.number << "\n"; cout << "salary = " << w2.salary << "\n"; } int main(){ Worker w1; strcpy(w1.name,"Takayuki"); w1.number =10; w1.salary = 100; cout << " Before shwodata" << "\n"; ShowData(w1); cout << " After shwodata" << "\n"; return 0; }

###補足情報(言語/FW/ツール等のバージョンなど)
paiza.io

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

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

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

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

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

guest

回答2

0

今回質問されているエラーについて何も記載されていませんので、怪しいところの指摘のみですが、コピーコンストラクタを書くとしたら

C++

1Worker::Worker(const Worker &obj){ 2 cout<< " This is Copy Constructor " << "\n"; 3 name = new char[80]; 4 strncpy(name, obj.name, 80); 5 this->number = obj.number; 6 this->salary = obj.salary; 7};

と書かないと、コピーされたオブジェクトを破棄する際に、もとのnameメンバも解放してしまいますよ。

あと、ちょっと苦言で申し訳ないですが、エラーの内容が判っているのは質問者さんのみで、ここを読んでいる人にはどういう操作をしたらエラーになった等の状況がさっぱりわかりません。エラーメッセージだけでなく、そういった情報もできるだけ書いてもらった方が的確な回答が集まりやすいです。

投稿2016/01/21 05:21

KoichiSugiyama

総合スコア3041

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

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

saito.kaz

2016/01/21 05:26

今回、エラー文が表示されず、上記のエラーメッセージのところに記載してある文のみでした。お手数をおかけし、申し訳ありません。
Chironian

2016/01/21 06:01

KoichiSugiyamaさんの回答でFinal Answerと思いますので、こちらで補足させて下さい。 TAKAYUKI_MIWAさん、先の質問からのトライですね。 下記はコンパイラが自動生成するものと事実上同じですので、コピーコンストラクタの生成をコンパイラに任せた場合と同じ結果になるのですよ。 > name = obj.name; 後、私のサンプル・コードでは初期化子を使ってました。まだC++初めて一週間の方に提示するのは適切でなかったかも。私が初期化子の存在を知ったのはC++を初めてたぶん10年後くらいだったような...ごめんなさい。 下記に初期化子を含めてC++のクラス定義について説明がありました。 http://homepage2.nifty.com/well/Class.html 中々良いサイトですので、時間がとれたら見てみることをお薦めします。
guest

0

ベストアンサー

コピーコンストラクタの以下の実装は問題があります。

C++

1name = new char[80]; 2name = obj.name;

name = new char[80]
により、新しいメモリをヒープ領域から確保し、その先頭アドレスが name に入りました。

ところが、
name = obj.name

として、name で保持していたアドレス値が、コピー元のnameのアドレス値に上書きされてます。
※コピーコンストラクタで渡される obj は、コピー元のインスタンスです。

先ほど確保したメモリのアドレスが行方不明になってしまうのはわかりますか?
そのため、先ほど確保したメモリを解放(delete)する機会が無くなってしまいます。

このオブジェクトがメソッドに渡されるたびに、解放されることのないメモリが確保されていくので、
やがてメモリリークを起こすことになります。

さらに、
name = obj.name
としているため、この関数終了のときに呼ばれるデストラクタで、コピー元の name が指し示すメモリが解放されます。
mainロジック完了の際に、もともとのオブジェクトも、デストラクタにより同一の name が指し示すメモリを解放してしまうため、2重解放になってしまいます。

これを解決するために、KoichiSugiyamaさんがご提示されているようにしなければなりません。

C++

1name = new char[80]; 2strncpy(name, obj.name, 80);

name = new char[80]
によって、新しいメモリ領域を割り当てたあと、strcpy によって、コピー元のobjのname の内容を、新しいメモリ領域にコピーしています。
(strcpyはバッファ上限を指定しないため、セキュリティ上脆弱です。利用しないことが推奨されており、KoichiSugiyamaさんはstrncpyにされています)

name には、新しく割り当てたメモリのアドレス値が入っていることを確認してください。

このメソッドが完了した際に呼ばれるデストラクタでは、
delete name
によって、新しく割り当てたメモリ領域が解放されることになります。

ポインタまわりは、難しいかもしれませんが、必ず腑に落ちるまで学習しておいたほうが良いと思います。
私は、こちらの書籍で理解できましたので、ご参考までに紹介させていただきます。

C言語ポインタ完全制覇

投稿2016/01/21 05:49

Toyoshima

総合スコア422

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

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

saito.kaz

2016/01/21 05:57

ありがとうございます。 とてもご参考になりました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問