2013-05-25 3 views
2

Я буду держать его коротким и понятным - для того, чтобы практиковать динамически выделенную память, я решил создать круг, в котором буду хранить его параметры (X и Y от центра и длины радиуса) в динамически распределенный массив. Поскольку массив динамически распределен, это означает, что для того, чтобы остановить утечку, я должен реализовать конструктор. Это также означает, что для того, чтобы избежать пары других ошибок, мне нужно реализовать конструктор копирования и перегрузить оператор присваивания. (с почти таким же кодом) Я думаю, что я реализовал деструктор достаточно хорошо. Тем не менее, мне нужна небольшая помощь с конструктором копирования.Копирующий конструктор и динамически распределенный массив

#include <iostream> 

using namespace std; 

class Circle 
{ 
private: 
    int* data; 
public: 
    Circle(){ 
     cout <<"I am the default constructor" << endl; 
     data = NULL; 
    } 
    Circle(int* p){ 
     cout <<"I am the set up constructor" << endl; 
     data = p; 
    } 
    ~Circle(){ 
     cout <<"I am the destructor" << endl; 
     delete data; 
    } 
    Circle& operator=(const Circle& tt1){ 
     cout << "Overloaded assignment operator reporting in!" << endl; 
     if(this != &tt1){ 
      //free old data 
      delete this->data; 
      data = new int(3); 
      *data = *(tt1.get_data()); 
      *(arr+1) = *(tt1->get_data()+1); 
      *(arr+2) = *(tt1->get_data()+2); 
      return *this; 
     } 
    } 
    Circle(const Circle& tt1){ 
     cout << "I am the copy constructor!" << endl; 
     if(this != &tt1){ 
      //free old data 
      delete this->data; 
      data = new int(3); 
      *data = *(tt1.get_data()); 
      *(arr+1) = *(tt1->get_data()+1); 
      *(arr+2) = *(tt1->get_data()+2); 
      return *this; 
     } 
    } 
}; 

int main(){ 
    //is this object constructed well? 
    int arr [] = { 16, 2, 7}; 
    Circle a(arr); 

    return 0; 
} 
+0

Примечания: 1) 'new int (3)' не делает то, что вы ожидаете от него ('data = new int [3]'). 2) Для каждого 'нового []' вам нужно 'delete []' ('delete [] data'). 3) 'int arr [] = {1,2,3}; int * ptr = arr; delete [] ptr; 'вызывает неопределенное поведение (мнемонический трюк: вы использовали' new [] '? Если вы этого не сделали,' delete [] 'будет ошибочным). – Zeta

+0

http://codereview.stackexchange.com –

+0

@Zeta: Где мнемоника? –

ответ

4
//is this object constructed well? 
int arr [] = { 16, 2, 7}; 
Circle a(arr); 

Ответ «да и нет»: Ваш конструктор не делает копию массива, он просто копирует указатель на первый элемент массива. Поэтому, если вы не хотите, чтобы ваш класс Circle имел собственный массив, вам не нужно предоставлять деструктор, копировать конструктор или оператор присваивания.

Но более вероятно, что вы do хотите, чтобы ваш класс владел массивом, и в этом случае вам нужно сделать локальную копию и сохранить его. Для этого вам понадобится одна дополнительная информация: размер массива, который полностью теряется при передаче (и реализует деструктор, конструктор копирования, оператор присваивания) функцию с указателем.

Edit, так как это упражнение в динамическом распределении в случае, когда массив ввода всегда размер 3, то это пример конструктора принимает массив:

Circle(int* p) 
{ 
    data = new int[3]; 
    std::copy(p, p+3, data); // UB if p doesn't point to an array of at least 3 elements 
} 

Вам нужно позвонить delete[] в деструкторе, так как вы назвали new[]:

~Circle() 
{ 
    delete [] data; 
} 

при выполнении оператора присваивания, рассмотрит copy and swap idiom.

+0

Да, я хочу, чтобы класс владел массивом. Поскольку я всегда буду использовать ровно 3 элемента, могу ли я пропустить его передачу? Кроме того, что было бы правильной конструкцией объекта, которому принадлежит массив? – Bloodcount

+0

@Bloodcount, если размер всегда три, тогда вам, вероятно, не нужно динамическое распределение. Итак, каковы реальные ограничения? – juanchopanza

+0

Я согласен с тем, что это плохой дизайн для работы с динамической памятью, однако я сейчас изучаю использование конструктора копирования, и хотя это не очень хороший пример, я хочу, чтобы он работал (мой план - реализовать мои собственная версия вектора немного позже, вот почему я использую динамически выделенный массив) – Bloodcount

-2

Я пишу правильный код о вашей практике, надеюсь, это может вам помочь. Я создаю это с помощью tdm-gcc, и он работает хорошо.

#include<iostream> 
#include<algorithm> //std::copy 
using namespace std; 

class Circle { 
private: 
int* data; 

public: 
Circle(){ 
    cout <<"I am the default constructor" << endl; 
    data = NULL; 
} 

Circle(int* p){ 
    cout <<"I am the set up constructor" << endl; 
    data =new int[3]; 
    copy(p,p+3,data); 
} 

~Circle(){ 
    cout <<"I am the destructor" << endl; 
    if (data!=NULL) { 
    delete[] data; 
    } 
} 

Circle(const Circle& tt1){ 
    cout << "I am the copy constructor!" << endl; 
    if (this != &tt1) { 
    if (data!=NULL) { 
    delete[] data; 
    } 

    data = new int[3]; 
    *data = *(tt1.get_data()); 
    *(data+1) = *(tt1.get_data()+1); 
    *(data+2) = *(tt1.get_data()+2); 
    } 
} 

Circle& operator=(const Circle& tt1){ 
    cout << "Overloaded assignment operator reporting in!" << endl; 
    if (this != &tt1) { 
    if (data!=NULL) { 
    delete[] data; 
    } 
    data = new int[3]; 
    *data = *(tt1.get_data()); 
    *(data+1) = *(tt1.get_data()+1); 
    *(data+2) = *(tt1.get_data()+2); 
    } 
} 

int* get_data() const { 
    return data; 
} 
}; 

int main(){ 
int arr[]={16,2,7}; 
Circle a(arr); 
cout<<*a.get_data()<<'\t' 
<<*(a.get_data()+1)<<'\t' 
<<*(a.get_data()+2)<<endl<<endl; 

return 0; 
} 
+1

Просто примечание: перед удалением не нужно проверять указатель на 'NULL'. – soon

+0

Я не уверен, что вы говорите правильно. Но спасибо вам большое. – jie

+0

Это так. Вы можете прочитать об этом в § 5.3.5 (2, 6, 7) C++ Standard – soon

Смежные вопросы