Работа оператора присваивания при копировании объектов

#c #operators #variable-assignment

#c #операторы #переменная-присваивание

Вопрос:

Оператор присваивания копирует один объект в другой по элементам. Если вы не перегружаете оператор присваивания, он выполняет побитовое копирование. Когда выполняется побитовое присваивание, оба объекта совместно используют одну и ту же ячейку памяти, и изменения в одном объекте отражаются в другом объекте. Эта концепция и мой код противоречат друг другу. Может кто-нибудь, пожалуйста, объяснить мне, почему..

 #include<bits/stdc  .h>
using namespace std;
class A
{
    public:
        int x;
};

int main()
{
    A a1,a2;
    a1.x=5;
    a2.x=5;
    a2=a1;
    a1.x=10;
    cout<<a1.x<<" "<<a2.x;
    return 0;
}
  

Комментарии:

1. «Если вы не перегружаете оператор присваивания, он выполняет побитовое копирование» Неверно. Он присваивает каждому члену, что для скалярных типов может означать побитовое копирование, но для классов он вызывает их операторы присваивания. И даже для скаляров «побитовое копирование» не означает совместное использование одной и той же памяти. Это означает копирование битов в другое место.

2. a2 = a1 не приводит к тому, что два объекта совместно используют одну и ту же ячейку памяти в C . В некоторых других языках (например, Java), где у нас есть ссылочная семантика, такое присваивание заставило бы обе переменные ссылаться на один и тот же объект — это не то, что делает C .

3. Ваш код не поддерживает ваше понимание, поэтому ваше понимание неверно. В частности, копирование — это копирование, а не совместное использование, и побитовое копирование не является членным. Оператором присваивания по умолчанию является копирование по элементам.

Ответ №1:

Когда выполняется побитовое присваивание, оба объекта совместно используют одну и ту же ячейку памяти, и изменения в одном объекте отражаются в другом объекте.

Это неверно. Назначение побитового копирования не приводит к тому, что объекты совместно используют одну и ту же память. Это отдельная копия, поэтому a2 и a1 фактически находятся в разных ячейках памяти.

Эта концепция и мой код противоречат друг другу.

Вы, вероятно, перепутали случай, когда присвоение копии выполняется с помощью переменной-члена-указателя. В этом случае, действительно, побитовое присваивание по умолчанию привело бы к тому, что объекты имели бы указатели, указывающие на одну и ту же память, и вместо этого требуется deep присваивание копирования (назначения по умолчанию).

Однако в вашем текущем коде нет ни одного элемента-указателя, поэтому такое глубокое копирование не требуется.

Комментарии:

1. хорошо, спасибо, это понятно .. Но я все еще путаюсь с конструктором копирования по умолчанию и оператором присваивания. Есть ли какая-либо разница в их работе.

2. @PriyaPatni то, как ты это написал a2=a1; , было присваиванием. Конструктор копирования по умолчанию был бы примерно таким: A a2(a1); итак, вы объявили a2 объект, используя конструктор копирования по умолчанию, с a1 — это объект, используемый для копирования в a2 .

3. мой вопрос заключается в том, выделяется ли в обоих случаях (т. Е. конструктор копирования по умолчанию и оператор присваивания) отдельная память для объектов

4. @PriyaPatni короткий ответ — да, два объекта будут иметь отдельную память в обоих случаях. Более длинный ответ — 1. Технически ни конструкторы копирования, ни операторы присваивания не выделяют память (выделение обрабатывается такими вещами, как прологи функций и новые операторы) — 2. Если каждый из двух объектов содержит указатель на член, сами указатели будут иметь отдельную память, но они оба могут указывать на одну и ту же память. Существуют «хитрости» (например, «размещение нового»), которые позволяют переопределить обычное поведение. — 3. Ссылки, являющиеся членами объектов, работают во многом так же, как указатели на члены.

Ответ №2:

Если вы используете указатель в своем классе, поскольку два объекта — источник и назначенный объект — обращаются к одному и тому же адресу памяти, поэтому, если вы измените это местоположение памяти, изменение будет видно для двух объектов.

 #include<bits/stdc  .h>
using namespace std;
class A
{
   public:
     int x;
     int *y;
};

int main()
{
 A a1,a2;
 a1.x=5;
 a1.y = new int(7);
 a2.x=5;
 a2=a1;
 a1.x=10;
 *a2.y = 9;
 cout<<a1.x<<" "<<a2.x;
 cout<<*a1.y<<" "<<*a2.y; // the output is 9 9/ because both object access two same memory address
 return 0;
}
  

Ответ №3:

Значения из a1 копируются в a2. Если бы у вашего класса был указатель, то значение указателя, то есть адрес, было бы скопировано таким же, что означало бы, что вы использовали один и тот же адрес, а затем изменение значения в одном из них также изменяет значение в другом.

Ответ №4:

Когда выполняется побитовое присваивание, оба объекта совместно используют одну и ту же ячейку памяти, и изменения в одном объекте отражаются в другом объекте.

неверно. Копирование есть копирование. Это означает, что данные из ячейки памяти для исходного объекта копируются в другую ячейку памяти для целевого объекта. Совместное использование ячейки памяти не выполняется.

Ответ №5:

Вы неправильно понимаете операторы присваивания по умолчанию, операторы присваивания по умолчанию используют метод копирования, известный как копирование по элементам. Я не буду делиться памятью.

Поскольку вы неправильно поняли концепцию, существует ожидаемое поведение.