C++ 何时调用复制构造函数和析构函数,为什么?
代码是:C++ 何时调用复制构造函数和析构函数,为什么?,c++,destructor,copy-constructor,C++,Destructor,Copy Constructor,代码是: #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(ne
#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;
}
#包括
类P_节点{
朋友班图片;
受保护的:
P_Node():使用(1){}
虚拟~P_节点(){}
私人:
int使用;
};
班级照片{
朋友相框(const Picture&);
公众:
Picture():p(新的p_节点){
std::cout在您认为可能或应该调用复制构造函数时,不一定会调用它:
以下情况可能导致调用复制构造函数:
当对象按值返回时
当对象以值作为参数传递(给函数)时
当抛出一个对象时
当捕捉到物体时
将对象放置在大括号内的初始值设定项列表中时
这些情况统称为复制初始化,相当于:tx=a
但是,,
不保证在这些情况下会调用副本构造函数,
因为C++标准允许编译器优化拷贝
在某些情况下,一个例子是
(有时称为RVO)
堆栈上的任何内容的析构函数在超出范围时都会被调用。复制构造函数不一定会在您认为可能或应该调用时被调用:
以下情况可能导致调用复制构造函数:
当对象按值返回时
当对象以值作为参数传递(给函数)时
当抛出一个对象时
当捕捉到物体时
将对象放置在大括号内的初始值设定项列表中时
这些情况统称为复制初始化,相当于:tx=a
但是,,
不保证在这些情况下会调用副本构造函数,
因为C++标准允许编译器优化拷贝
在某些情况下,一个例子是
(有时称为RVO)
堆栈上任何内容的析构函数在超出范围时被调用。回答您的问题
在语句Picture temp=frame(my_pic);
之后不会调用copy构造函数,因为没有任何语句会导致该语句之后出现任何副本
调用Picture
的三个析构函数(按顺序):temp
,p
在temp.p
和my_Pic
指向的帧Pic
中进行销毁。编译器已避免生成任何其他临时Picture
对象
是的,可以调用复制构造函数来初始化图片帧(const Picture&pic)
的返回值,但允许编译器(在这种情况下确实如此)消除复制并直接从返回表达式初始化返回值
是的,如果将frame
的参数更改为按值传递,则可能会生成额外的复制构造函数调用,但如果该参数是用一个表达式初始化的,而该表达式不是引用现有对象的glvalue,则参数可能会直接用该表达式初始化,并且该副本会被省略
每当类类型的对象被实际复制时,就会调用复制构造函数。这可能是在传递给函数或从函数返回时调用的,但在这些情况下,编译器有时可以忽略不必要的副本
是的,每当类类型的对象被销毁时都会调用析构函数。对于编译器生成的命名变量和临时变量来说,这是正确的。可以在不调用析构函数的情况下结束对象的生命周期,例如,我将其内存重新用于另一个对象,但这是一个非常特殊的情况
回答你的问题
在语句Picture temp=frame(my_pic);
之后不会调用copy构造函数,因为没有任何语句会导致该语句之后出现任何副本
调用Picture
的三个析构函数(按顺序):temp
,p
在temp.p
和my_Pic
指向的帧Pic
中进行销毁。编译器已避免生成任何其他临时Picture
对象
是的,可以调用复制构造函数来初始化图片帧(const Picture&pic)
的返回值,但允许编译器(在这种情况下确实如此)消除复制并直接从返回表达式初始化返回值
是的,如果将frame
的参数更改为按值传递,则可能会生成额外的复制构造函数调用,但如果该参数是用一个表达式初始化的,而该表达式不是引用现有对象的glvalue,则参数可能会直接用该表达式初始化,并且该副本会被省略
每当类类型的对象被实际复制时,就会调用复制构造函数。这可能是在传递给函数或从函数返回时调用的,但在这些情况下,编译器有时可以忽略不必要的副本
是的,每当类类型的对象被销毁时都会调用析构函数。对于编译器生成的命名变量和临时变量来说,这是正确的。可以在不调用析构函数的情况下结束对象的生命周期,例如,我将其内存重新用于另一个对象,但这是一个非常特殊的情况
注意:在所有说明将调用复制构造函数的答案中,可能不会调用复制构造函数,因为编译器进行了一些优化
1) 为什么不在Picture temp=frame(my_pic)
之后调用copy constructor
Picture temp=frame(my_pic);是return语句之前的最后一行,因此所有这些都会发生
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