0

int a = b;

или

int a; a = b;

Проходил конструкторы копирования , и выяснил что при одном из них конструктор копии работает , а при другом нет! В чем же разница ?

  • 2
    Если речь идет о "конструкторах копирования", то почему в примере фигурирует тип int, у которого никаких "конструкторов" нет и быть не может? – AnT stands with Russia Dec 11 '19 at 01:59
  • int это скалярный тип данных. Для скалярных типов данных определенны операторы +,-,= и т.д. , смотрите ниже я привел пример, как Ваш вопрос будет выглядеть на asm, и почему разницы нет...:) – microup Dec 12 '19 at 10:16

2 Answers2

3

В случае

int a = b;

объявляется переменная a, которая сразу же инициализируется путём копирования значения переменной b.

В случае

int a; a = b;

объявляется переменная a, происходит инициализация по умолчанию. Для типа данных int инициализация по умолчанию означает, что у объекта будет некое неопределённое значение.

Уже после этого переменной a присваивается значение переменной b.

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

T a;     // вызывается конструктор по умолчанию.
T b;     // вызывается конструктор по умолчанию.
T c = a; // вызывается конструктор копирования.
c = b;   // конструктор не вызывается
ВЛ 80
  • 791
  • 1
    В случае int a; не происходит инициализация по умолчанию. В обьект записываются те данные, которые существуют в ячейках памяти, выделенной для обьекта, т.е. мусор. P. S. Компилятор вполне может заменить этот код первым вариантом. – AR Hovsepyan Dec 11 '19 at 06:43
  • 1
    @ARHovsepyan В объекте действительно мусор, но формально это все равно инициализация, см. https://ru.cppreference.com/w/cpp/language/default_initialization – HolyBlackCat Dec 11 '19 at 07:48
  • @HolyBlackCat, читайте пожалуйста внимательно: я сказал, что в обьект записываются...(это та же инициализация), а замечание было по поводу инициализации по умолчанию. – AR Hovsepyan Dec 11 '19 at 08:33
  • @ARHovsepyan читайте, пожалуйста, внимательно: "The effects of default initialization are: ... nothing is done: the objects with automatic storage duration (and their subobjects) are initialized to indeterminate values." Инициализация по умолчанию ничего не делает в данном случае, но это не значит, что она "не происходит" как вы выразились. – αλεχολυτ Dec 11 '19 at 08:49
  • @αλεχολυτ, неопределенное значение не есть дефолт значение, так что я остаюсь при своем мнении: инициализация по умолчанию не происходит. Ничего не сделано и означает, что не происходит... – AR Hovsepyan Dec 11 '19 at 09:17
  • @ARHovsepyan ну, если вы не смогли распарсить фразу "initialized to indeterminate values", то я, конечно, переубеждать не буду. – αλεχολυτ Dec 11 '19 at 10:07
  • @αλεχολυτ, думаю, что наша дальнейшая беседа по этой теме становится не полезной, но чтобы понять, что объявление локального обьекта int a; это не то же самое, что int a {}; мне не нужно читать стандарт или учебник... В любом случаи, спасибо за обсуждение! – AR Hovsepyan Dec 11 '19 at 10:53
  • 1
    @ARHovsepyan int a{} - это value initialization, а int a; - default initialization. – αλεχολυτ Dec 11 '19 at 11:01
  • да, я образно выразился, хотел короче, а получилось...не совсем как всегда, но все же не то – AR Hovsepyan Dec 11 '19 at 11:06
-2

int это скалярный тип, для работы с данными типами предопределены операторы =,+,- и т.д и ни каких конструкторов... В данном случае оператор = выполняет операцию копирования - значения RVALUE (b) в левую часть LVALUE (a). В вашем вопросе разнице ни какой нет, ниже будет пример, почему. В обоих случаях будет вызывать один и тот же оператор копирования =.


Для справки и тем кто минусует, про RValue. Берем вырезку из стандарта "2012 - Standarts for C++ - Drafts - N3337 - Finall 11" про RVALUE из раздела 3.10 Lvalues and rvalues:

An rvalue (so called, historically, because rvalues could appear on the right-hand side of an assignment expression) is an xvalue, a temporary object (12.2) or subobject thereof, or a value that is not associated with an object.

Теперь перевод google translate:

Rvalue (исторически так называемое, потому что rvalue может появляться в правой части присваивания expression) - это xvalue, временный объект (12.2) или подобъект или значение, которое не связано с объектом.


Вывод:

Когда пишем int a = b, 1е говорим компилятору, что хотим в стеке выделить 4 байта под тип int и 2е даем компилятору команду копирования "=", что по указанному адресу записать значение b (RValue).

и на закуску... есть онлайн решение, которое переводит Ваш код в asm, https://godbolt.org/

Вот как выглядит для компилятора Ваши объявления: к примеру:

int square(int b) {
    int a;
    a = b;
}

square(int):
        push    rbp
        mov     rbp, rsp
        mov     DWORD PTR [rbp-20], edi
        mov     eax, DWORD PTR [rbp-20]
        mov     DWORD PTR [rbp-4], eax
        nop
        pop     rbp
        ret

и следующий вариант кода:

// Type your code here, or load an example.
int square(int b) {
    int a = b;
}

square(int):
        push    rbp
        mov     rbp, rsp
        mov     DWORD PTR [rbp-20], edi
        mov     eax, DWORD PTR [rbp-20]
        mov     DWORD PTR [rbp-4], eax
        nop
        pop     rbp
        ret

найдите отличия? Всегда надо смотреть что написано в стандарте и разбираться, как Ваш код воспринимает и обрабатывает компилятор!

microup
  • 665
  • обоснуйте минус, пожалуйста?! – microup Dec 11 '19 at 08:45
  • 1
    При инициализации вида T a = b; никакого вызова operator= нет. Хотя для встроенных типов это вообще странно упоминать. Ну и b не является rvalue, почитайте, например, тут. – αλεχολυτ Dec 11 '19 at 09:05
  • хорошо почитайте тогда стандарт N3337 https://github.com/tpn/pdfs/blob/master/C%2B%2B%20Standard%20-%202012-01-16%20-%20Working%20Draft%20(N3337).pdf и выше, раздел 3.10 Lvalues and rvalues, что такое Rvalue. И если возникает противоречие, то надо смотреть в стандарт в первую очередь. – microup Dec 11 '19 at 12:37
  • 1
    Зачем тут ссылка на черновик восьмилетней давности? Вот вам вырезка из свежего: Historically, lvalues and rvalues were so-called because they could appear on the left- and right-hand side of an assignment (although this is no longer generally true) – αλεχολυτ Dec 11 '19 at 12:46
  • ну во первых ни где не сказано про стандарт ни слова. написал исходя из того стандарта, который проверен временем и на данный момент имеет очень большое распространение. – microup Dec 11 '19 at 13:15