-1

私は大きな問題を抱えています-つまり、私のコードでは、デストラクタがオブジェクトを削除しません。これを呼び出すl3.~list();と、メインの下に貼り付けられますが、単一リンクリストのみが削除されます(これは良いことです)が、char*名も削除されません私は私のデストラクタで述べていますがdelete [] name;。何かアイデアは何が悪いのですか?

これがコードです。

#include <iostream>
#include <cstdlib>
#include <string>
using namespace std;

class list{

    struct lista
    {
        int num;
        char* word;
        lista* next;
    };
    lista* head;
    char* name;
    public:
    list(char* name1){head=NULL;name=new char[strlen(name1)+1];strcpy(name,name1);}
    char getChar(int key, int index);
    void setChar(int key, int index, char c);
    void insert(int number,char* txt);
    void remove(int number);
    void print();
    list(const list &o);
    list& operator=(const list &x);
    ~list();
};
void list::insert(int number,char* txt){
    lista* ptr,*tmp;
    ptr=head;
    lista* newlista=new lista;
    newlista->num=number;
    newlista->next=NULL;
    newlista->word= new char[strlen(txt)+1];
    strcpy(newlista->word,txt);
    if(head==NULL){
        head=newlista;
        newlista->next=NULL;
    }
    else while(ptr!=NULL){
        if(strcmp(txt,ptr->word)>=0){
            if(ptr->next!=NULL && strcmp(txt,ptr->next->word)<=0)
            {
                tmp=ptr->next;
                ptr->next=newlista;
                newlista->next=tmp;
                break;
            }
            else if(ptr->next!=NULL && strcmp(txt,ptr->next->word)>0)
                ptr=ptr->next;
            else
            {
                //next is empty
                ptr->next=newlista;
                break;
            }
        }
        else{
            //txt mniejszy niz w 1szym elemencie
            newlista->next=head;
            head=newlista;
            break;
        }      
    }
    return;
}

void list::print(){
    cout<<name<<";"<<endl;
    lista *druk;
    druk=head;
    while(druk!=NULL){
        cout<<"txt: "<<druk->word<<" | "<<"num: "<<druk->num<<endl;
        druk=druk->next;
    }
    cout<<endl;
    return;
}


void list::remove(int number){
    if(head==NULL)
        return;
    if(head->num==number){
        lista* ptr=head;
        head=head->next;
        delete [] ptr->word;
        delete ptr;
        return;
    }
    lista* ptr=head;
    while(ptr->next!=NULL && ptr->next->num!=number)
        ptr=ptr->next;
    if(ptr->next==NULL){
        cout<<number<<" element not found"<<endl;
        return;
    }
    lista* todelete=ptr->next;
    ptr->next=todelete->next;
    delete [] todelete->word;
    delete todelete;
    return;
}
list::list(const list &o)
{
    lista *xtr = o.head;
    head=NULL;// bez tego nie działa
    lista *etr=head;// nastawic etr na head?
    while (xtr)
    {
        lista* ntr = new lista;
        if (!ntr)
        {
            cerr << "list::CopyConstructor: Allocation memory failure!";
            cerr << endl;
            break;
        }
        ntr->num = xtr->num;
        ntr->word= new char[strlen(xtr->word)+1];
        strcpy(ntr->word,xtr->word);
        ntr->next = NULL;
        if (head)
            etr->next = ntr;    
        else
            head = ntr;
        etr = ntr; // keep track of the last element in *this
        xtr = xtr->next;
    }
    name = new char[strlen(o.name)+5];
    strcpy(name,o.name);
    strcat(name,"Copy");
}

list& list::operator=(const list &x)
{
    if(this==&x)
        return *this;
    lista *etr=head;
    while(etr) // removing list from this
    {
        etr=etr->next;
        delete head;
        head=etr;
    }
    lista *xtr=x.head;
    while(xtr)
    {
        int copied=xtr->num;
        lista *ntr= new lista;
        ntr->word=new char[strlen(xtr->word)+1];
        if (!ntr) 
        {
            cerr << "list::operator=: Allocation memory failure!" << endl;
            break;
        }
        ntr->num=copied;
        strcpy(ntr->word,xtr->word);
        ntr->next=NULL;
        if (!head)
            head = ntr;
        else
            etr->next = ntr;

        etr = ntr; // keep track of the last element in *this
        xtr = xtr->next;
    }
    char *name=new char[strlen(x.name)+1];
    strcpy(name,x.name);
    return *this;
}

list::~list()
{
    cout<<"Object with name:"<<name<<" destroyed!"<<endl;
    delete [] name;
    lista *dtr=head;
    while(dtr) // removing lista from this
    {
        dtr=dtr->next;
        delete [] head->word;
        delete head;
        head=dtr;
    }

}
void f();
void f(){
    list o("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
    o.insert(4,"kazio");
    o.insert(100,"312jh31io2");
    o.insert(34,"kz31231azio");
    o.insert(1020,"123213312jh31io2");
    o.insert(213123,"z3213io");
    o.insert(1100,"zdrf312jh31io2");
    o.print();
}
int main(){
    list l1("lista1");
    l1.insert(5,"Endian");
    l1.insert(7,"Endianness");
    l1.insert(100,"Hexediting");
    l1.insert(34,".mil");

    l1.print();
    list l2(l1); // usage of CC - the same as list l2=l1; 
    l2.print();
    l2.remove(5);
    l2.print();
    l1.print();

    list l3("asajnment");
    l3=l2=l1;
    l3.print();
    l2.print();
    f();
    l3.print();
    l3.~list(); // here i use destructor on l3
    l3.print(); // l3 is being printed with weird name, even though it should be destroyed
    getchar();
    return 0;
}
4

5 に答える 5

5

デストラクタを呼び出した後に任意のメソッドを呼び出すと、未定義の動作が発生します。動作する場合と動作しない場合があり、奇妙な結果が生じる可能性があります。

また、デストラクタを直接呼び出すことは想定されていません。

  • オブジェクトがスタックに割り当てられると、スコープが終了すると自動的に破棄されます。(スコープは中括弧の間のものです{}
  • オブジェクトが を使用してヒープに割り当てられている場合は、 を使用して破棄するnew必要がありますdelete
于 2012-04-18T18:46:06.770 に答える
1

C ++デストラクタは、Cで記述できるような割り当て解除関数とは異なります。より優れています。RAIIイディオムでは、オブジェクトがスコープを終了する瞬間にオブジェクトの破棄がスケジュールされています。つまり、通常はリソースを解放する必要はまったくありません。オブジェクトが不要になるまで待つだけです(アクセスできないため)。その時点で、オブジェクトは自動的に削除されます(デストラクタの呼び出しを含む、はい)。 、そしてそれが安全に呼び出される唯一の方法です)。したがって、適切に記述されたC ++は、多くの点でガベージコレクションされた言語と同じくらい優れていますが、いくつかの欠点はありません。

RAIIのメリットを享受する最も簡単な方法は、標準のコンテナーとスマートポインターを使用することです。あなたの場合、とをに置き換えlista* nextてください。デストラクタを定義する必要がなくても、すべて問題ありませstd::unique_ptr<lista> nextchar* wordstd::string word

于 2012-04-18T18:56:03.930 に答える
1

このコードには多くの問題があるため、どこから始めればよいかわかりません...

  • std::string を使用
  • std::map を使用して int 値を文字列に関連付けます。これは、すでにあなたが望むことをほとんど行っています。
  • 新規作成されていないものに対してデストラクタを呼び出さないでください。何かを削除するには、delete/delete[] を使用し、デストラクタを直接呼び出さないでください。new を使用する場合は、std::unique_ptr や std::shared_ptr などの管理オブジェクトを使用する RAII イディオムを使用して、delete/delete[] を手動で呼び出す必要がないようにし、例外セーフ コードを記述します。

こちらは少し改良されたバージョンです。new/delete への単一の呼び出しがないことに注意してください。

#include <iostream>
#include <string>
#include <map>
#include <cstdio>

class list
{
public:
    explicit
    list( std::string n ) : name( n ) {}

    ~list() { std::cout << "~list:" << name << std::endl; }

    void list::insert(int number, std::string const& txt ){
        items.insert( std::make_pair(number,txt));
    }

    void list::remove(int number){
        items.erase( number );
    }

    void print( ){
        std::cout << name << ";" << std::endl;
        for( Items::const_iterator it = items.begin(), end = items.end(); it != end; ++it  )
        {
            std::cout << "num: " << it->first << " | " << "txt: " << it->second << std::endl;
        }
        std::cout << std::endl;
    }

private:
    typedef std::map<int,std::string> Items;
    Items items;
    std::string name;
};

int main()
{
    list l1( "lista1" );
    l1.insert( 5, "Endian");
    l1.insert( 7, "Endianness");
    l1.insert( 100, "Hexediting");
    l1.insert( 34, ".mil");
    // extra scope so the destructor of l2 is called before call to getchar
    { 
        list l2( l1 ); 
        l2.remove( 5 );
        l2.print();
    }
    l1.print();

    getchar();
    return 0;
}
于 2013-02-14T21:32:04.777 に答える
0

破棄後にメンバーが誤ってアクセスされていないことを確認する1つの方法は、メンバーを削除した後、すべてのポインターをNULLに設定することです。

そうすれば、あなたはもはやあなたの機密データを指さないので、後で誰もあなたの機密データにアクセスできないことが保証されます。また、NULLポインターでdeleteを呼び出すことは許可されており、何も行わないため、悪影響を与えることなくデストラクタを再度呼び出すことができます。

于 2012-04-18T18:56:44.277 に答える
-1

オブジェクトを削除した後にオブジェクトのメモリ状態を出力すると、新しいオブジェクトを割り当てない限り、値が保持されていることがわかります。プログラムに割り当てられるメモリは、大きくなるだけです。データを削除すると、データは「0」に設定されず、次の alloc オブジェクト用に空きとしてマークされるだけです。

編集:つまり、解放した直後に初期化されていない値で新しいオブジェクトを作成すると、メモリに保存されている古い値を取り戻すことができます。

于 2012-04-20T07:36:25.220 に答える