![](http://oshiete.xgoo.jp/images/v2/pc/qa/question_title.png?e8efa67)
C++を勉強していて解らないことがあったので質問させていただいたのですが、
とあるスコープで生成したインスタンスを、
スコープ外で参照しても問題なく値が取り出せるのですけども、
これは処理的には問題ないのでしょうか?
例のソースを以下に示します。
struct Hoge {
inta, b;
};
void testA(){
Hoge*hoge;
if( true ){
Hogetmp;
tmp.a = 1;
tmp.b = 2;
hoge = &tmp;
}
std::cout << hoge->a << "," << hoge->b << std::endl;
}
void testB(){
Hoge*pHoge;
if( true ){
Hoge *pTmp = new Hoge();
pTmp->a = 1;
pTmp->b = 2;
pHoge = pTmp;
}
std::cout << pHoge->a << "," << pHoge->b << std::endl;
delete pHoge;
pHoge = NULL;
}
上記の場合、どちらも画面に 1,2 と出力されますが、
アドレスが上書きされていないだけで今の時点では偶然エラーが出ないけども潜在的なバグがあったり、
処理的にいつ落ちるかわからないなどの問題はあったりしますか?
ご存知の方がいらっしゃいましたらアドバイスをお願いします
No.3ベストアンサー
- 回答日時:
こんにちは。
御礼頂き有難う御座います。>>連結リストクラスなるものの内部でインスタンスを生成しアドレスを前後でつなぎ、最終的にデストラクタで全て解放するように考えていたのですが、
>>こういったことはあまり実用的ではないのでしょうか?
いえ、流石に実用的で無いと言う訳では無いのですが、処理の過程でポインタ複写されて重複する事もあり、うっかりすると2重削除が起こったりしやすくなります。
場合にもよりますが、そのままポインタを扱い続けるよりは、参照カウント方式のスマートポインタを扱った方が、手っ取り早くて安全度が高いです。
少なくとも、「newとdeleteが一対か?」と言う呪われたお話に付き合う必要はなくなります。
以下参考を示しますが、極小さなコードなので、中々恩恵が実感できないかもしれません。STLとBOOSTを使用しています。
//必要な物
#include<list>
#include<algorithm>
#include<boost/shared_ptr.hpp>
//削除用のコールバック
void Delete(Hoge* p)
{
cout << "[pointer deleted : " << p << "]" << endl;
delete p;
}
//通常のポインタ
int main()
{
Hoge* a[] =
{
new Hoge(), new Hoge(), new Hoge()
};
std::list<Hoge*> ls(a, a + 3);
//Hogeポインタを任意で削除しなければいけない
std::for_each(ls.begin(), ls.end(), &::Delete);
return 0;
}
//スマートポインタ
int main()
{
typedef boost::shared_ptr<Hoge> sptr;
sptr a[] =
{
sptr(new Hoge(), &::Delete), sptr(new Hoge(), &::Delete), sptr(new Hoge(), &::Delete)
};
std::list<sptr> ls(a, a + 3);
//何もする必要は無い。スマートポインタのデストラクタが勝手に動いてHogeポインタを消す。
//また、std::list<sptr> ls2 = ls; の様に複写しても2重削除される事も無い。
return 0;
}
ご返答ありがとうございます。
サンプルソースまで乗せていただいて感謝します。
私自身がスマートポインタ等の理屈を十分に理解できていないのでさっと見た感じではありますが、
この場合だと二重で削除されて強制終了や解放漏れ・・・
なんてことは無さそうなのでより安全ではありますよね。
生成時と解放時に必ず1度だけ呼ばれるのですから。
アドバイスいただいたソースを元に自分なりに色々と手を加えてみたいと思います。
ありがとうございます。
No.4
- 回答日時:
testB の方はこれだけみると変だけど, (new/delete の問題を除けば) 特におかしくもないですよ.
「ある関数の中で new で確保し, その領域をそのまま返す」というのはまさにこれの延長線上にあるわけだから. まあ混乱すると簡単に死ねるのでスマートポインタを使うなり GC 使うなりした方がいいと思うけど.
ご返答ありがとうございます。
言われてみれば確かに、
FactoryMethodパターンなんかはそうですよね。
そうならば納得できます。
うーん、やっぱり普通にnew/deleteを使うのでは、
先の方も仰られたとおり解放し忘れや二重解放がありますし・・・。
このまま使わずに、何かしらの方法を考えたいと思います。
No.2
- 回答日時:
こんばんは。
>>アドレスが上書きされていないだけで今の時点では偶然エラーが出ないけども潜在的なバグがあったり、
TestAに関してはその通りです。
これは明らかにNGです。まだ残骸が残っているのでしょう。完全な間違いである、と言う事です。
TestBはOKですが、厳密には長丁場に置いてこの様な事をしていると・・・。
確かに長丁場でやっていると、
解放し忘れなどが気になりますよね。
その辺りは十分に注意するようにします・・・。
ただ一応可能とのことなので、
連結リストクラスなるものの内部でインスタンスを生成しアドレスを前後でつなぎ、最終的にデストラクタで全て解放するように考えていたのですが、
こういったことはあまり実用的ではないのでしょうか?
ご回答に更に質問で返すようで申し訳ないですが、
ご存じでしたらご返答いただければ大変嬉しいです
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# プログラミングのペーパーテスト 実行結果を表示せよ #include <stdio.h> int h 1 2022/07/09 15:27
- C言語・C++・C# プログラミングのペーパーテスト 実行結果がどのように表示されるか答えよ #include <stdi 1 2022/07/09 14:27
- HTML・CSS 全部のアクセスを指定したページに転送させたい 2 2022/06/28 16:33
- Windows 10 バッチファイルの記述法とルールについてアドバイスをお願いいたします。 1 2022/04/13 10:50
- JavaScript ifreamをリロードしたい 1 2022/05/03 16:15
- JavaScript JavaScriptで「〇以上▲まで」の書き方 1 2022/07/20 14:44
- XML XML同じ名前の要素を自動で集約するツール 1 2022/04/11 09:21
- Visual Basic(VBA) VBAでの共有パスにつきまして 1 2023/03/04 17:24
- JavaScript javascriptで文字分割は、 split() などメソッド不要??? 4 2023/02/06 22:50
- その他(プログラミング・Web制作) pythonのcondaコマンドの仕様について 2 2022/06/24 00:13
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
init関数の意味
-
Run-Time Check Failure #3とい...
-
C言語のポインタに直接アドレス...
-
LPSTR型の初期化について
-
PASCALとFARの意味
-
単方向リスト
-
C言語でのconstを返す関数
-
別のDLLのダイアログを・・・
-
関数ポインタの利点
-
デバイスハンドルとは?
-
戻り値で構造体を返すことは可...
-
参照型で受け取った引数をポイ...
-
ハンドル、アドレス、ポインタ...
-
C++で関数ポインタから関数名を...
-
DirectXのDIRECT3DTEXTURE9
-
セグメントエラー
-
fopne で失敗する原因
-
gccでMAKEINTRESOURCEするとdif...
-
登録した文字列をランダムに表...
-
どうしてエラーになるかわかり...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
セグメントエラー
-
C言語のポインタに直接アドレス...
-
fopne で失敗する原因
-
init関数の意味
-
Run-Time Check Failure #3とい...
-
戻り値で構造体を返すことは可...
-
LPSTR型の初期化について
-
Cで作成したDLL関数をVBから呼...
-
ExcelVBAでのkernel32(64bit)
-
アプリを32bitから64bit移行
-
構造体とfscanf
-
c言語で任意のファイルから読み...
-
デバイスハンドルとは?
-
main(int argc,char **argv[])...
-
基本アルゴリズムの『返す』の...
-
コンストラクタでnewを失敗した...
-
C言語の関数と配列に関する質問
-
参照型で受け取った引数をポイ...
-
ハンドル、アドレス、ポインタ...
-
DLL<->VB間での受け渡し(文字...
おすすめ情報