Почему вызывается конструктор копирования?
От: na1s  
Дата: 05.10.07 21:04
Оценка:
Явный косяк с логикой.
#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? Этому есть разумное объяснение, почему сделано именно так?
Re: Почему вызывается конструктор копирования?
От: VoidEx  
Дата: 05.10.07 21:16
Оценка:
Здравствуйте, 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
Re: Почему вызывается конструктор копирования?
От: filkov СССР  
Дата: 05.10.07 21:23
Оценка:
Здравствуйте, 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.

Так надо
Санкционный Смотритель.
Re: Почему вызывается конструктор копирования?
От: Erop Россия  
Дата: 05.10.07 22:34
Оценка:
Здравствуйте, na1s, Вы писали:

N>Явный косяк с логикой.

<...>
N>Почему печатает 1st, хотя должен 2nd? Этому есть разумное объяснение, почему сделано именно так?

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

Смотри:
 std::string str1 = "ма"; // в str1 завели буффер, который содержит текст "ма"
std::string str2 = str1 + str1; // в str2 завели буффер, который содержит текст "мама"
// при этом никакой предыдущий буфер не освобождали, так как вызвался конструктор
str1 = str2 + str2; // А теперь позвали оператор присваивания, так что старый буфер освободили, 
// и завели новый, под строку "мама"


Вот примерно по=этому так и сделали
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re: Почему вызывается конструктор копирования?
От: FallAngel Украина  
Дата: 05.10.07 22:39
Оценка: +1 :))
Здравствуйте, 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
"...наставники более мудры не благодаря умению действовать, а потому, что они обладают отвлеченным знанием и знают причины..." Аристотель.
Re: Почему вызывается конструктор копирования?
От: Roman Odaisky Украина  
Дата: 06.10.07 08:58
Оценка:
Здравствуйте, na1s, Вы писали:

N>Явный косяк с логикой.


Как, по-твоему, должен работать твой код («A a, b = a»)? A::A(), A::A(), A::operator =? Наоборот, логично, что нет лишнего вызова дефолтного конструктора.
До последнего не верил в пирамиду Лебедева.
Re: Почему вызывается конструктор копирования?
От: Чили Россия  
Дата: 08.10.07 06:14
Оценка:
Здравствуйте, na1s, Вы писали:

N>Явный косяк с логикой.


Прочти статьи Классы: копирование и присваивание. http://www.interface.ru/home.asp?artId=7344
Re: Почему вызывается конструктор копирования?
От: moorgeist  
Дата: 08.10.07 10:07
Оценка:
Здравствуйте, na1s, Вы писали:

N>Почему печатает 1st, хотя должен 2nd? Этому есть разумное объяснение, почему сделано именно так?

Как вам уже ответили, программа корректна и выдает верные сообщения. Но если хотите, то можете перед именем конструктора ставить ключ explicit. Тогда компилятор будет ругаться, когда конструктора копирования с одним параметром вызывается неявно, т.е. через =, а не через ().
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.