Я новичок в C++, и у меня проблема с моим конструктором копирования: мне нужно сделать глубокую копию, потому что в моем классе есть указатели. Я уже определил конструктор копирования, а также создаю объект N1(2,3)
из своего класса Number
. Второй объект N2
инициализируется с помощью конструктора копирования.
Но конструктор копирования не выполняет глубокое копирование, потому что, когда я изменяю значение объекта N1
, значения объекта N2
также изменяются. Я хочу иметь два отдельных объекта с помощью конструктора копирования.
Номер моего класса:
class Number
{
private:
int* a;
int* b;
public:
//default constructor:
Number() {
a = new int;
b = new int;
*a = 0;
*b = 0;
}
//constructor with arguments:
Number(int val1, int val2) {
a = new int;
b = new int;
*a = val1;
*b = val2;
}
//copy constructor:
Number(const Number& other) {
a = new int;
b = new int;
*a = *(other.a)
*b = *(other.b);
}
//getters and setters:
int getA() {
return *a;
}
int getB() {
return *b;
}
void setA(int val) {
*a = val;
}
void setB(int val) {
*b = val;
}
//method print:
void print() {
cout << "value of a: " << *a << " value of b: " << *b << endl;
}
};
Мой основной:
int main()
{
Number N1(2,3), N2;
N1.print(); //2-3
N2.print(); //0-0
N2 = N1;
N1.print(); //2-3
N2.print(); //2-3
N1.setA(12);
N1.print(); //12-3
N2.print(); //12-3 i want object N2 have 2-3 values not 12-3 like N1
//i want to separate N1 from N2 by using copy constructor
}
Я пытаюсь определить этот конструктор копирования, но он не работает:
//copy constructor:
Number(const Number& other) {
a = new int;
b = new int;
*a = *(other.a)
*b = *(other.b);
}
я уже проверил это: Number(const Number&other) { a = new int; б = новый интервал; *а = *(другое.а); *b = *(другое.b); } // но и этот синтаксис не работает
Также правильным решением было бы не выделять динамически один int
, так как это не имеет смысла.
«мне нужно сделать глубокую копию, потому что в моем классе есть указатели» нет. Если в вашем классе есть указатели, которые не должны быть указателями, вам нужно избавиться от указателей. Отсутствующая глубокая копия — это лишь одна из многих проблем в вашем коде, вызванных бессмысленным использованием указателей. Если это «я хочу попрактиковаться с указателями», то ок, урок, который нужно усвоить здесь: это не вариант использования указателей.
Нет необходимости сначала выделять, а затем назначать. a = new int(0);
, a = new int(val1);
, a = new int(*other.a);
.
N2 = N1;
вызывает оператор присваивания копирования, а не конструктор копирования.
этот синтаксис не работает - The Definitive C++ Book Guide and List
Ваш код никогда не использует конструктор копирования.
как я могу вызвать конструктор копирования?
важно, чтобы вы прочитали это en.cppreference.com/w/cpp/language/rule_of_three
Вы не называете это; он вызывается за вашей спиной, когда вы инициализируете новый объект как копию оригинала. Попробуйте Number N1(2,3); Number N2(N1); N1.setA(12); N1.print(); N2.print();
@molbdnilo спасибо, я использую этот синтаксис Number N1 (2,3); Номер N2(N1); и это работает 100%
Проблема, которую вы видите, заключается в отсутствии Полного правила 0/3/5.
И тот факт, что вы не вызываете свой конструктор копирования. Вы вызываете оператор присваивания, который был предоставлен для вас и является поверхностным.
Строка Number N1(2,3), N2;
объявила N2
с помощью конструктора по умолчанию.
Строка N2 = N1;
затем мелко копирует N1
, потому что вы не указали operator=()
.
Если вы хотите вызвать конструктор копирования, вы должны сделать это во время объявления. Ведь это конструктор.
Что-то вроде Number N2(N1);
.
Чтобы завершить свой код, вам все еще нужно написать деструктор, а также оператор присваивания. Тогда пришло время узнать о семантике перемещения.
Код N2 = N1;
не вызывает конструктор копирования, потому что N2
уже создан. Скорее, он вызывает оператор присваивания. Поскольку вы не предоставили определение для этого, по умолчанию делается неглубокая копия (т.е. просто копируется/перезаписывается фактические указатели, как вы заметили).
Вам нужно определить оператор присваивания с глубоким копированием; что-то вроде этого:
// assignment operator:
Number& operator=(const Number& other) {
*a = *(other.a);
*b = *(other.b);
return *this;
}
Обратите внимание, однако, что если бы вы использовали синтаксис = N1
в объявлении N2
(как показано ниже), это вызвало бы конструктор копирования:
Number N2 = N1; // This calls the copy constructor
new int(*a = *(other.a))
?? Откуда вы взяли этот синтаксис?