#include <iostream>
using namespace std;
class A
{
public:
A(){}
A(const A &a){cout<<"1st";}
A& operator =(A&){cout<<"2nd";}
};
int main()
{
A b;
A a=b;
return 0;
}
Почему печатает 1st, хотя должен 2nd? Этому есть разумное объяснение, почему сделано именно так?
Здравствуйте, na1s, Вы писали:
N>Явный косяк с логикой. N>
N>#include <iostream>
N>using namespace std;
N>class A
N>{
N>public:
N> A(){}
N> A(const A &a){cout<<"1st";}
N> A& operator =(A&){cout<<"2nd";}
N>};
N>int main()
N>{
N> A b;
N> A a=b;
N> return 0;
N>}
N>
N>Почему печатает 1st, хотя должен 2nd? Этому есть разумное объяснение, почему сделано именно так?
Не должен.
12.8
A class object can be copied in two ways, by initialization (12.1, 8.5), including for function argument
passing (5.2.2) and for function value return (6.6.3), and by assignment (5.17). Conceptually, these two
operations are implemented by a copy constructor (12.1) and copy assignment operator (13.5.3).
2 A non-template constructor for class X is a copy constructor if its first parameter is of type X&, const X&,
volatile X& or const volatile X&, and either there are no other parameters or else all other
parameters have default arguments (8.3.6).106)
[Example:
X::X(const X&) and X::X(X&, int=1)
are copy constructors.
class X {
// ...public:
X(int);
X(const X&, int = 1);
};
X a(1); // calls X(int);
X b(a, 0); // calls X(const X&, int);
X c = b; // calls X(const X&, int);
—end example]
8.5
A declarator can specify an initial value for the identifier being declared. The identifier designates an
object or reference being initialized. The process of initialization described in the remainder of 8.5 applies
also to initializations specified by other syntactic contexts, such as the initialization of function parameters
with argument expressions (5.2.2) or the initialization of return values (6.6.3).
initializer: = initializer-clause
( expression-list )
initializer-clause:
assignment-expression
{ initializer-list ,opt }
{ }
initializer-list:
initializer-clause
initializer-list , initializer-clause
Здравствуйте, na1s, Вы писали:
N>Почему печатает 1st, хотя должен 2nd? Этому есть разумное объяснение, почему сделано именно так?
SomeClass p = q; // copy constructor is used to initialize in declaration.
p = q; // Assignment operator, no constructor or copy constructor.
f(p); // copy constructor initializes formal value parameter.An object is returned by a function.
Здравствуйте, na1s, Вы писали:
N>Явный косяк с логикой.
<...> N>Почему печатает 1st, хотя должен 2nd? Этому есть разумное объяснение, почему сделано именно так?
К сожалениб косяк с логикой не у авторов стандарта...
Сделано так потому, что конструктор -- это метод, который вызывается для создания нового экземпляра объекта класса. То есть до вызова конструктора экземпляр не инициализирован, а оператор присваивания вызывается у уже созданного объекта, так что он должен учитывать имеющееся на момент вызова состояние объекта. Вот в этом и кроется разница.
Смотри:
std::string str1 = "ма"; // в str1 завели буффер, который содержит текст "ма"
std::string str2 = str1 + str1; // в str2 завели буффер, который содержит текст "мама"
// при этом никакой предыдущий буфер не освобождали, так как вызвался конструктор
str1 = str2 + str2; // А теперь позвали оператор присваивания, так что старый буфер освободили,
// и завели новый, под строку "мама"
Вот примерно по=этому так и сделали
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, na1s, Вы писали:
N>Явный косяк с логикой. N>
N>#include <iostream>
N>using namespace std;
N>class A
N>{
N>public:
N> A(){}
N> A(const A &a){cout<<"1st";}
N> A& operator =(A&){cout<<"2nd";}
N>};
N>int main()
N>{
N> A b;
N> A a=b;
N> return 0;
N>}
N>
N>Почему печатает 1st, хотя должен 2nd? Этому есть разумное объяснение, почему сделано именно так?
Доброговремени суток. Проблема в том, что писать надо не:
A b;
A a=b;
,а
A b;
A a;
a = b;
тогда все работает
Происходит энто от того, что в первом случае компилятор производит инициализацию экземпляра класса и по энтому вызывает конструктор.По крайней мере похоже на то, потому что второй вариант работает и выводится 2nd
"...наставники более мудры не благодаря умению действовать, а потому, что они обладают отвлеченным знанием и знают причины..." Аристотель.
Здравствуйте, na1s, Вы писали:
N>Явный косяк с логикой.
Как, по-твоему, должен работать твой код («A a, b = a»)? A::A(), A::A(), A::operator =? Наоборот, логично, что нет лишнего вызова дефолтного конструктора.
Здравствуйте, na1s, Вы писали:
N>Почему печатает 1st, хотя должен 2nd? Этому есть разумное объяснение, почему сделано именно так?
Как вам уже ответили, программа корректна и выдает верные сообщения. Но если хотите, то можете перед именем конструктора ставить ключ explicit. Тогда компилятор будет ругаться, когда конструктора копирования с одним параметром вызывается неявно, т.е. через =, а не через ().