Код:Когда вызываются конструкторы и деструкторы копирования и почему?
#include <iostream>
class P_Node {
friend class Picture;
protected:
P_Node() : use(1) {}
virtual ~P_Node() {}
private:
int use;
};
class Picture {
friend Picture frame(const Picture&);
public:
Picture() : p(new P_Node) {
std::cout << "Constructor\t" << "Picture::Picture()" << "\tcalled" << std::endl;
std::cout << "Picture p count\t" << p->use << std::endl;
}
Picture(const Picture& orig) : p(orig.p) {
std::cout << "Copy Constructor\t" << "Picture::Picture(const Picture&)" << "\tcalled" << std::endl;
std::cout << "Picture p count\t" << p->use << std::endl;
orig.p->use++;
}
~Picture() {
std::cout << "Destructor\t" << "Picture::~Picture()" << "\tcalled" << std::endl;
std::cout << "Picture p count before decrease\t" << p->use << std::endl;
if(--p->use == 0) {
std::cout << "Picture p count after decrease\t" << p->use << std::endl;
std::cout << "Deleted" << std::endl;
delete p;
}
}
Picture& operator=(const Picture& orig) {
std::cout << "operator=\t" << "Picture& Picture::operator=(const Picture& orig)" << "\tcalled" << std::endl;
std::cout << "Picture p count before decrease\t" << p->use << std::endl;
orig.p->use++;
if(--p->use == 0) {
std::cout << "Picture p count after decrease\t" << p->use << std::endl;
std::cout << "Deleted" << std::endl;
delete p;
}
p = orig.p;
return *this;
}
private:
Picture(P_Node* p_node) : p(p_node) {
std::cout << "Picture::Picture(P_Node* p_node)\tcalled" << std::endl;
}
P_Node *p;
};
class Frame_Pic : public P_Node {
friend Picture frame(const Picture&);
private:
Frame_Pic(const Picture& pic) : p(pic) {
std::cout << "Frame_Pic::Frame_Pic(const Picture& orig)" << "\tcalled" << std::endl;
}
Picture p;
};
Picture frame(const Picture& pic) {
return new Frame_Pic(pic);
}
int main() {
Picture my_pic;
Picture temp = frame(my_pic);
return 0;
}
Результат:
Constructor Picture::Picture() called Picture p count 1 Copy Constructor Picture::Picture(const Picture&) called Picture p count 1 Frame_Pic::Frame_Pic(const Picture& orig) called Picture::Picture(P_Node* p_node) called Destructor Picture::~Picture() called Picture p count before decrease 1 Picture p count after decrease 0 Deleted Destructor Picture::~Picture() called Picture p count before decrease 2 Destructor Picture::~Picture() called Picture p count before decrease 1 Picture p count after decrease 0 Deleted
я уже задал вопрос об управлении памятью этого кода, но после понимания ответов, я до сих пор есть проблемы с деструктор и конструктор копирования. По моему мнению, Picture temp = frame(my_pic)
вызовет конструктор копирования.
Здесь возникает вопрос:
- Почему не конструктор копирования вызывается после
Picture temp = frame(my_pic)
- и почему деструктор с именем?
- В
Picture frame(const Picture& pic)
будет вызван конструктор копирования, если функция вызывается? Я так считаю, потому что он возвращает значение «Изображение» по значению. - Если я изменю
Picture frame(const Picture& pic)
наPicture frame(Picture p)
, будет ли конструктор копирования дважды вызываться при вызове функции? - Когда будет вызываться конструктор копирования? Это произойдет, когда класс будет возвращен функцией по значению? Когда тогда класс передается функции по значению?
- Когда будет вызван деструктор? Это когда каждый раз, когда срок жизни переменной заканчивается? Означает ли это, что если передать переменную функции по значению, ее деструктор будет вызываться после выполнения функций?
Я сейчас испорчен конструктором копирования и деструктором, особенно когда у меня есть функция с возвращаемым значением и некоторые параметры, все переданные значениями.
Также, кто-нибудь поможет мне написать комментарий к каждой строке строк вывода? Это было бы очень полезно.
Обратите внимание, что вызовы для копирования конструкторов и операторов присваивания могут быть свободно устранены оптимизатором компилятора, даже если они имеют побочные эффекты. Это единственные два, для которых компилятору разрешено нарушать правило as-if. (Конечно, компилятор по-прежнему должен не нарушать логику и сопоставлять вызовы ctors и dtors.) – sbi
@outis: Нет. Возвращаемое выражение имеет тип 'Frame_Pic *'.'Frame_Pic' получен из' P_Node' и 'P_Node *' неявно конвертируется в 'Picture' через закрытый конструктор, который отлично подходит, поскольку' frame' объявлен другом. Тело возвращает «Изображение», так как объявляется функция. –
@CharlesBailey, поэтому код не _wrong_ как таковой, но я определенно не назвал бы эту хорошую практику. – bames53