Почему адрес назначенного объекта не изменяется в C ?

#c #class #memory-address #assignment-operator #copy-assignment

#c #класс #адрес памяти #оператор присваивания #копирование-присвоение

Вопрос:

В этом примере C класс C имеет конструктор по умолчанию, конструктор копирования и оператор присваивания:

 struct C {
    C();
    C(const Camp; c);
    Camp; operator=(const Camp; c);
};
  

Реализация выглядит следующим образом с некоторым выводом для отслеживания объектов. Я добавил несколько примеров адресов в комментариях к строкам в качестве ссылки на main программу ниже.

 #include "C.h"
#include <iostream>
using namespace std;

C::C() {
    cout << "Standard constructor." << endl;
}

C::C(const Camp; c) {
    cout << "Copy constructor." << endl;
}

Camp; C::operator=(const Camp; c) {
    cout << "Address of reference argument: amp;c = " << amp;c << endl;      // F9B4
    cout << "Address of this: amp;*this =           " << amp;*this << endl;  // F8D4
    return *this;
}
  

Я буду использовать фабричный метод, который возвращает анонимные объекты:

 C foo() {
    return C();
}
  

Теперь в следующей программе я создаю именованный объект c (см. (1)) и создаю анонимный объект (2), который я присваиваю c (3). Я ожидал, что c после назначения будет указан адрес анонимного объекта.

 int main()
{
    C c;  // (1)
    cout << "Address of initial c from main: amp;c = " << amp;c << endl;                  // F8D4
    c=foo();  // (2) and (3)
    cout << "Address of initial c from main after assignment: amp;c = " << amp;c << endl; // Expected F9B4 but is F8D4
}
  

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

1. c является локальной переменной. Его адрес не изменится.

2. = просто копирует внутреннее содержимое. Вы не можете изменить адрес переменной, объявленной в стеке

3. Переменная — это поле с именем; внутри него хранится значение. c является таким полем; foo() создает и возвращает анонимное поле. Оператор присваивания = не влияет на поля, он копирует содержимое из одного поля в другое.

4. Я не думаю, что адрес объекта можно изменить, независимо от того, размещен ли он в стеке или в свободном хранилище.

5. Стоит отметить, что если вы пришли с C # или Java, легко получить эту путаницу.

Ответ №1:

Объекты в C никогда не меняют адреса.

Оператор присваивания ничем не отличается от любого другого метода, обычно он просто перебирает все переменные-члены и присваивает им новые значения, скопированные из соответствующих членов другого объекта.

Ответ №2:

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

 C c;
  

Ответ №3:

Я ожидал, что после назначения c будет иметь адрес анонимного объекта.

Объекты в C размещаются в стеке, если явно не указано new .

В этом случае вы просто создаете временный анонимный объект, а затем копируете его c . c имеет то же местоположение в стеке, что и раньше.

Причина, по которой вы можете не видеть сообщение конструктора копирования c=foo(); , заключается в том, что что-то называется copy elision , по которой, я полагаю, вы думали c , что будет храниться анонимный объект, а не просто его копия.