首先是代码,它来自'Ruminations on C ++'第10章
// TestCode.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
#include <string>
#include <conio.h>
using namespace std;
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)
{
cout << "Constructor\t" << "Picture::Picture()" << "\tcalled" << endl;
cout << "Picture p count\t" << p->use << endl;
}
Picture(const Picture& orig) : p(orig.p)
{
cout << "Copy Constructor\t" << "Picture::Picture(const Picture&)" << "\tcalled" << endl;
cout << "Picture p count\t" << p->use << endl;
orig.p->use++;
}
~Picture()
{
cout << "Destructor\t" << "Picture::~Picture()" << "\tcalled" << endl;
cout << "Picture p count before decrease\t" << p->use << endl;
if(--p->use == 0)
{
cout << "Picture p count after decrease\t" << p->use << endl;
cout << "Deleted" << endl;
delete p;
}
}
Picture& operator=(const Picture& orig)
{
cout << "operator=\t" << "Picture& Picture::operator=(const Picture& orig)" << "\tcalled" << endl;
cout << "Picture p count before decrease\t" << p->use << endl;
orig.p->use++;
if(--p->use == 0)
{
cout << "Picture p count after decrease\t" << p->use << endl;
delete p;
}
p = orig.p;
return *this;
}
private:
Picture(P_Node* p_node) : p(p_node)
{
// Why not p_node->use++?
cout << "Picture::Picture(P_Node* p_node)\tcalled" << endl;
}
P_Node *p;
};
class Frame_Pic : public P_Node
{
friend Picture frame(const Picture&);
private:
Frame_Pic(const Picture& pic) : p(pic)
{
cout << "Frame_Pic::Frame_Pic(const Picture& orig)" << "\tcalled" << endl;
}
Picture p;
};
Picture frame(const Picture& pic)
{
return new Frame_Pic(pic);
}
int main(int argc, char* argv[])
{
Picture my_pic;
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
我对此代码有两个问题:
Frame_Pic
的构造函数之前调用复制构造函数?在我看来,调用了复制构造函数,因为frame(my_pic)
按值返回Picture
。但是应该在Frame_Pic
的构造函数之后调用它。Picture::Picture(P_Node* p_node)
中,为什么不增加使用次数?这不是创建一个新的Picture
?感谢您的帮助。
我在Windows XP下使用VC6。
答案 0 :(得分:1)
1,为什么在Frame_Pic的构造函数之前调用Copy Constructor?
因为p
成员是在Frame_pic的构造函数的初始化列表中进行复制构造的。初始化列表在输入构造函数体之前运行。
声明在我看来,调用了复制构造函数,因为frame(my_pic)按值返回Picture。但是应该在Frame_Pic的构造函数之后调用它。
frame()
按值返回Picture
个实例,但它被编码为返回Frame_pic*
。 Frame_pic
派生自P_node
,Picture
有一个接受P_node*
的构造函数,frame()
可以访问该构造函数,因此编译器允许它。
2,In Picture :: Picture(P_Node * p_node),为什么不增加使用次数?这不是创造一个新的图片吗?
使用次数为P_node
,而不是Picture
。 Picture
返回的frame()
拥有Frame_pic
创建的frame()
,其使用计数成员已由Frame_pic
构造函数设置为1。这就是Picture
构造函数不会增加使用次数的原因 - 它已经是正确的值。
Frame_pic
包含自己的Picture
,它是从另一个Picture
复制构造的,因此Picture
构造函数需要增加原始{{1}的使用次数}}
答案 1 :(得分:0)
Frame_Pic(const Picture& pic) : p(pic)
{
cout << "Frame_Pic::Frame_Pic(const Picture& orig)" << "\tcalled" << endl;
}
您使用其复制构造函数'p(pic)'初始化'p',因此它会按您看到的顺序调用
答案 2 :(得分:0)
: p(pic)
调用)。但是,在运行所有初始化程序之后,Frame_Pic的构造函数才会打印。P_Node*
进行手动控制,然后再将其归还的情况。但是附加语义不太可能,因为没有相应的分离机制来返回指针并清除它而不减少引用计数。所以,很可能是一个错误。请注意,虽然这种手动引用计数可以作为学习练习,但现代C ++代码通常使用智能指针(例如std::shared_ptr
或boost::shared_ptr
,invasive_ptr
等)自动化过程。