c++ - 这段代码是如何运行的?

标签 c++ memory-management smart-pointers

首先是代码,它来自“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

关于这段代码我有两个问题:

  1. 为什么复制构造函数在Frame_Pic 的构造函数之前被调用?在我看来,调用复制构造函数是因为 frame(my_pic) 按值返回 Picture。但这应该在 Frame_Pic 的构造函数之后调用。
  2. Picture::Picture(P_Node* p_node)中,为什么不增加使用次数呢?这不是在创建一个新的Picture吗?

感谢您的帮助。

我在 Windows XP 下使用 VC6。

最佳答案

1, Why is the Copy Constructor called before Frame_Pic's Constructor?

因为p成员在Frame_pic的构造函数的初始化列表中被复制构造。初始化列表在进入构造函数主体之前运行。

In my mind, the Copy Constructor is called because frame(my_pic) is returning a Picture by value. But that should be called after Frame_Pic's Constructor.

frame() 被声明为按值返回一个 Picture 实例,但它被编码为返回一个 Frame_pic*Frame_pic 派生自 P_nodePicture 有一个接受 P_node* 的构造函数,并且该构造函数可访问frame() 所以编译器允许它。

2, In Picture::Picture(P_Node* p_node), why not increase the use count? isn't this creating a new Picture?

使用次数是在P_node上,而不是在Picture上。 frame()返回的Picture拥有frame()创建的Frame_pic,其use count成员已经1 通过 Frame_pic 构造函数。这就是为什么 Picture 构造函数不会增加使用计数 - 它已经处于正确的值。

Frame_pic 包含它自己的 Picture,它是从另一个 Picture 复制构造的,因此 Picture 构造函数需要增加原始图片的使用次数。

关于c++ - 这段代码是如何运行的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8686573/

相关文章:

c++ - 如何为对象提供不同的接口(interface)(最佳)

c++ - 如何使用 MPI 发送 3D 数组的切片?

c++ - 如何在 C++ 中访问函数作用域变量?

c++ - weak_ptr 如何知道共享资源已过期?

r - R Windows 64 位版本中尚不支持长向量错误

ios - 堆内存的持久化分配 NSTimer

c++ - 似乎无法将 unique_ptr 分配给结构

c++ - 具有单个互斥体的 std::scoped_lock 行为

c++ - 指向 int 的指针。 C++

java - 如何真正释放 Linux 中的大页面以供新进程使用?