Listă dinamică de numere întregi în C++ (Programare, C++, Array-Uri, Dinamic, Constructor De Copii)

zacharoni16 a intrebat.

Încerc să creez o matrice dinamică în clasa mea List, care va începe cu o dimensiune de 2 și atunci când introduceți valori cu metoda Insert, va verifica dacă există suficient spațiu, dacă nu, va redimensiona matricea cu o dimensiune + 2… Problema este că se blochează VS se plânge de coruperea heap-ului. De asemenea, cred că constructorul meu de copiere nu este apelat deoarece couturile nu se afișează:

list.h File:

class List
{
public:

    //  DEFAULT Constructor
    List();
    // Deconstructor to free memory allocated 
    ~List();// Prevent memory leaks

    // COPY Constructor for pointers
    List(const List& value);// copy constructor

    //Modification methods
    void Insert(const int);

    // User ACCESS methods
    void display(void) const;

private:
    int size;// MAX size of the array          
    int count;// current number of elements in the dynamic array

protected:
    int *intptr;// Our int pointer
};

list.cpp fișier de implementare:

#include "list.h" // Include our Class defintion
#include <iostream>

using namespace std;

// CONSTRUCTOR
List::List() {
    size = 2; // initial size of array
    count = 0;
    intptr = new int[size]; // Start off 2 integers sized array
}
// DECONSTRUCTOR
List::~List() {
    delete[] intptr; // free allocated memory
}

// Copy constructor

List::List(const List& value) {
    size = value.size;
    cout << "Copy con size : " << size << endl;
    count = value.count;

    cout << "Compy count : " << count << endl;
    if (count < size) {
        intptr = new int[size]; // Allocate new data
    } else {
        intptr = new int[size + 2]; // Allocate new data
    }

    for (int index = 0; index < count; index++) {
        intptr[index] = value.intptr[index];
    }

    size = size + 2;
    delete[] intptr;
    intptr = value.intptr;
}

void List::Insert(const int value) {
    // do we have room?
    if (count < size) {
        intptr[count] = value;
    } else { // if not we need to add more elements to array
        intptr[count] = value; // DEEP copy invoked with copy constructor
    }

    cout << "SIZE: " << size << endl;
    cout << "COUNT" << count << endl;
    count++; // Increase items added in array
}

void List::display() const {
    for (int i = 0; i < count; i++)
        cout << intptr[i] << endl;
}

main.cpp tester

#include <iostream>
#include "list.h"

int main()
{
    List mylist;

    mylist.Insert(5);
    mylist.Insert(6);
    mylist.Insert(2);
    mylist.Insert(8);
    mylist.Insert(4);
    mylist.Insert(5);
    mylist.Insert(9);
    mylist.Insert(8);
    mylist.Insert(5);
    mylist.Insert(9);
    mylist.Insert(8);
    mylist.Insert(5);
    mylist.Insert(9);
    mylist.Insert(8);
    mylist.Insert(5);
    mylist.Insert(9);

    mylist.display();

    system("PAUSE");
    return 0;
}

Comentarii

  • Cum se face indexarea unui int * și atribuirea rezultatului cheamă constructorul de copiere al clasei tale? –  > Por chris.
  • Afirmați că se efectuează o copie profundă, dar nu pare să existe. Cum vă așteptați să se realizeze o copie a listei? V-ați gândit să actualizați dimensiunea tabloului pe care îl utilizați în loc să vă bazați pe constructorul de copiere? –  > Por Will.
  • De ce nu folosiți std::vector sau std::list în loc să vă scrieți propria clasă? Ambele sunt liste care cresc în mod dinamic. std::vector is an array, much like your class, whereas În schimb, std::list` este o listă legată de noduri de arbore. –  > Por Remy Lebeau.
  • Credeam că este invocată automat? –  > Por zacharoni16.
  • Constructorul de copii ar fi invocat automat, dacă ați face vreodată o copie. Nu o faceți. Creați o instanță și apoi apelați insert de mai multe ori. Este un fel de temă pentru acasă? Nu mă pot gândi de ce ai vrea să faci asta în mod normal, decât dacă poate încerci să controlezi memoria mai bine decât o face std::vector, deoarece dublează dimensiunea de fiecare dată când are nevoie de mai mult… –  > Por Cdaragorn.
4 răspunsuri
Remy Lebeau

Nu gestionați corect array-ul, mai ales în Insert() metoda. Încearcă asta în schimb:

#include "list.h" // Include our Class defintion 
#include <iostream> 

// CONSTRUCTOR 
List::List()  
{ 
    intptr = new int[2];
    size = 2;
    count = 0; 

    std::cout << "Initial size : " << size << " count : " << count << std::endl; 
} 

// DECONSTRUCTOR 
List::~List() 
{ 
    delete [] intptr; // free allocated memory 
} 

// Copy constructor 
List::List(const List& value) 
{ 
    intptr = new int[value.size]; // Allocate new data 
    size = value.size; 
    count = value.count; 

    for(int index = 0; index < count; ++index) 
        intptr[index] = value.intptr[index]; 

    std::cout << "Copy size : " << size << " count : " << count << std::endl; 
} 

void List::Insert(const int value) 
{ 
    if (count == size)
    { 
        int *newintptr = new int[size+2];

        for(int index = 0; index < size; ++index) 
            newintptr[index] = intptr[index]; 

        delete[] intptr;
        intptr = newintptr;
        size += 2;
    }

    intptr[count] = value; 
    ++count;

    std::cout << "New size : " << size << " count : " << count << std::endl; 
} 

void List::display() const 
{ 
    for(int i = 0; i < count; i++) 
        std::cout << intptr[i] << std::endl; 
} 

.

#include <iostream> 
#include "list.h" 

int main() 
{ 
    List mylist; 

    mylist.Insert(5); 
    mylist.Insert(6); 
    mylist.Insert(2); 
    mylist.Insert(8); 
    mylist.Insert(4); 
    mylist.Insert(5); 
    mylist.Insert(9); 
    mylist.Insert(8); 
    mylist.Insert(5); 
    mylist.Insert(9); 
    mylist.Insert(8); 
    mylist.Insert(5); 
    mylist.Insert(9); 
    mylist.Insert(8); 
    mylist.Insert(5); 
    mylist.Insert(9); 

    mylist.display(); 
    system("PAUSE"); 

    List mylist2(myList); // copy construct a new list

    mylist2.display(); 
    system("PAUSE"); 

    return 0; 
} 

Acestea fiind spuse, ar trebui să folosiți cu adevărat std::vector în schimb, de exemplu:

#include <iostream>            
#include <vector>
#include <algorithm>

void displayValue(int value)
{
    std::cout << value << std::endl; 
}

int main()            
{            
    std::vector<int> mylist;            

    mylist.push_back(5);            
    mylist.push_back(6);            
    mylist.push_back(2);            
    mylist.push_back(8);            
    mylist.push_back(4);            
    mylist.push_back(5);            
    mylist.push_back(9);            
    mylist.push_back(8);            
    mylist.push_back(5);            
    mylist.push_back(9);            
    mylist.push_back(8);            
    mylist.push_back(5);            
    mylist.push_back(9);            
    mylist.push_back(8);            
    mylist.push_back(5);            
    mylist.push_back(9);            

    std::for_each(mylist.begin(), myList.end(), displayValue);
    system("PAUSE");            

    std::vector<int> myList2(myList);

    std::for_each(mylist2.begin(), myList2.end(), displayValue);
    system("PAUSE");            

    return 0;            
 }       

Pentru a face un pas mai departe, dacă doriți să continuați să utilizați metoda dvs. personalizată List cel puțin utilizați std::vector în interiorul acesteia:

#include <vector>

class List  
{  
public:  
    //  DEFAULT Constructor  
    List();  

    //Modification methods  
    void Insert(const int);  

    // User ACCESS methods  
    void display(void) const;  

protected:  
    std::vector<int> intvec;
};

.

#include "list.h" // Include our Class defintion 
#include <iostream> 

// CONSTRUCTOR 
List::List()  
{ 
    intvec.reserve(2);
    std::cout << "Initial size : " << intvec.capacity() << " count : " << intvec.size() << std::endl; 
} 

// Copy constructor 
List::List(const List& value) 
{ 
    intvec = value.intvec;
    std::cout << "Copy size : " << invec.capacity() << " count : " << intvec.size() << std::endl; 
} 

void List::Insert(const int value) 
{ 
    intvec.push_back(value); 
    std::cout << "New size : " << intvec.capacity() << " count : " << intvec.size() << std::endl; 
} 

void List::display() const 
{ 
    for(std::vector<int>::const_iterator iter = intvec.begin(), end = intvec.end(); iter != end; ++iter) 
        std::cout << *iter << std::endl; 
} 

.

#include <iostream> 
#include "list.h" 

int main() 
{ 
    List mylist; 

    mylist.Insert(5); 
    mylist.Insert(6); 
    mylist.Insert(2); 
    mylist.Insert(8); 
    mylist.Insert(4); 
    mylist.Insert(5); 
    mylist.Insert(9); 
    mylist.Insert(8); 
    mylist.Insert(5); 
    mylist.Insert(9); 
    mylist.Insert(8); 
    mylist.Insert(5); 
    mylist.Insert(9); 
    mylist.Insert(8); 
    mylist.Insert(5); 
    mylist.Insert(9); 

    mylist.display(); 
    system("PAUSE"); 

    List mylist2(myList); // copy construct a new list

    mylist2.display(); 
    system("PAUSE"); 

    return 0; 
} 

Comentarii

  • Se pare că încerc să fac prea multe cu constructorul de copiere și funcționează diferit decât am crezut, mulțumesc, studiez codul tău acum –  > Por zacharoni16.
alestanis

List::Insert(const int value) nu apelează metoda List constructor de copiere, ci doar scrie în interiorul intptr array. Când count devine mai mare decât size, , se scrie în afara tabloului și de aceea apar erori.

Ar trebui să mutați ceea ce faceți în constructorul de copiere în constructorul Insert direct în metoda Copy.

Comentarii

  • Cum ar trebui totuși să fie apelat constructorul de copiere, este confuz…  > Por zacharoni16.
  • Constructorul de copiere ar fi apelat dacă ați face vreodată o copie a unei instanțe a obiectului. Cu alte cuvinte, dacă ai avea două instanțe ale listei tale, a și b, și ai spune a = b.  > Por Cdaragorn.
  • Încercați să adăugați List myotherlist(mylist); în fișierul principal și veți vedea toate acele couts apar 🙂 –  > Por alestanis.
BigBoss

Motivul pentru copy-constructor este de a crea un nou obiect din unul existent, dar uită-te la tine copy-constructor, ce faci acolo?

/* initialize my size and count, from value */
size = value.size;
count = value.count;

/* Check count and size */
if( count == size ) /* if other is full */
    size += 2;

/* copy content from value.intptr into this->intptr */
//if (count < size)
//    intptr = new int[size]; // Allocate new data
//else
//    intptr = new int[size + 2]; // Allocate new data
intptr = new int[size];  /* Allocate my buffer */

/* It's better to use std::copy in place of a hand written loop */
//for(int index = 0; index < count; index++)
//    intptr[index] = value.intptr[index];
std::copy( value.intptr, value.intptr + value.count, intptr );

/* why you increase your size here?? shouldn't this indicate size of intptr? */
//size = size + 2;

/* After creating a new buffer and putting data into it, you destroy the buffer
   and set your buffer equal to buffer of value? why? if value destroyed it will
   destroy its intptr and your intptr point to a deleted memory
*/
//delete [] intptr;
// intptr = value.intptr;

Acum uitați-vă la insert metoda:

if(count < size) // do we have room?
{
    intptr[count] = value;
}
else // if not we need to add more elements to array
{
    /* As you already checked you do not have enough room to insert data to intptr
       so why you do it here? shouldn't you first allocate a new buffer and then
       copy data to it?
       In comment you say DEEP copy with copy-constructor, which copy constructor
       you expect to called here? you are assigning an int to another int, so where
       is copy constructor?
     */
    // intptr[count] = value; // DEEP copy invoked with copy constructor
    int* tmp = new int[size + 2];
    std::copy( intptr, intptr + size, tmp );
    delete[] intptr;
    intptr = tmp;
    size += 2;
    intptr[count] = value;
}

count++; // Increase items added in array

Comentarii

  • @user978563 Nu Cred că ești norocos că poți învăța repede 🙂 –  > Por BigBoss.
SecuritateMatt

Utilizați std::vector. Face deja toate acestea, și o face mai sigur și mai rapid decât o va face codul tău.