2016-10-13 2 views
0

現在、私はC++のメモリ管理に関する問題に直面しています。その割り当てられた(新しい)オブジェクトをスコープの外に削除します

for(auto &person : persons) 
... 
    SomeClass::cpy(&(person.name_), new_name); 
... 

私の問題は、その範囲の外でTMP変数を削除することであるように

void SomeClass::cpy(char** dest, const char* origin) 
{ 
    int len = strlen(origin); 
    char* tmp = new char[len+1]; 
    strncpy(tmp, origin, len); 
    tmp[len] = '\0'; 
    *dest = tmp; 
} 

関数呼び出しが見えます。私はその価値が必要なので、この範囲の終わりにそれを削除することはできません。 delete[] name_;でクラスのデストラクタを使用すると、メモリに違反しているようです。

+1

スコープの外に何を意味するのですか? –

+4

私は、手動メモリ操作とポインタをmuckingするのではなく、 'std :: string'と参照パラメータを使うことを強くお勧めします。 – NathanOliver

+0

私は関数内にtmpを割り当てているので、どこからでもそれを削除することはできません。 – Mer0winger

答えて

0

* destにtmpを戻しています。だから、あなたがそれで終わったら、がchar*と仮定して、delete person.name_とすることができます。

1

現代のC++では、オブジェクトを所有するために裸のポインタを使用することは悪い習慣と考えられます。代わりにstd :: unique_ptrを使用すると、メモリが削除されたときに確実に解放されます。また、出力引数を使用する代わりに、関数から値を返す方が望ましいです。それはもはや必要ないときにメモリを削除する責任があります

std::unique_ptr<char> SomeClass::cpy(const char* origin) 

この方法でstd::unique_ptrにあなたのメソッドのシグネチャを変更します。

具体的な使用例については、具体的には文字列を扱うように設計されているので、std::stringを使用することをお勧めします。

+5

*現代のC++では、裸のポインタ*を使うのは悪い習慣とみなされます*少し誤解を招くことです。生の*所有*ポインタを使うのは悪い習慣です。所有していないポインタは問題ありません。 – NathanOliver

+0

ありがとう、ネイサン。私は答えを修正しました。 –

1

迅速なウォークスルー:

void SomeClass::cpy(char** dest, const char* origin) 
{ 
    int len = strlen(origin); 
    char* tmp = new char[len+1]; 

メモリのブロックがちょうど動的に割り当てられました。このブロックは、手動でdelete[]を解放するまで存在します。

strncpy(tmp, origin, len); 
    tmp[len] = '\0'; 
    *dest = tmp; 

以前に割り当てられたメモリブロックはdestに割り当てられています。 destを提供した人は、delete[]を使用して、割り当てごとに1回だけ実行される限り、いつでもこのメモリを解放することができます。

} 

は今、発信者

SomeClass::cpy(&(person.name_), new_name); 

person.name_destは1と同じであることを指定しています。つまり、delete[] person.name_;は完全に受け入れられます。

しかし...

これは、上記のいずれもしないし、std::stringとメモリ管理苦境を軽減するための優れた場所のように見えます。 std::stringは、あなたのためにそのメモリを見ます。

std::string SomeClass::cpy(const char* origin) 
{ 
    return std::string(origin); 
} 

person.name_ = SomeClass::cpy(new_name); 

person.name_一旦char *からstd::stringに変換されます。

person.name_ = new_name; 

があなたのためにすべての作業を行いますので、しかし、すぐにそれがSomeClass::cpyを行われているように冗長です。

+0

あなたはそれを一つ上に置いて、 'std :: string SomeClass :: cpy(std :: string origin){原点を返します。 } ' – NathanOliver

+0

@NathanOliver良い点。また、値渡しと参照渡しを説明するページと半分の長いスクリードの可能性を開く。 – user4581301

関連する問題