簡體   English   中英

破壞和分配的順序

[英]Order of destruction and assignment

我正在開發一個Entity類,它需要通過setter方法提供對其數據成員的訪問,setter方法在存儲之前檢查一個值(檢查代碼未顯示)。 Select類是存儲的類型之一,它需要在銷毀時進行一些非常具體的清理:

#include<memory>
#include <iostream>
using namespace std;

class Select {
    int i, j;

    friend class Entity;

public:
    Select(int a, int b) : i{a}, j{b} { }

    ~Select() {
        cout << "destroying " << i << j << endl;
    }

protected:
    Select() { };
};

class Entity {

    Select select_;

public:
    void select_setter(const Select &select) {
        cout << "to be assigned... " << select.i << select.j << endl;
        select_ = select;
    }

    static shared_ptr<Entity> create(const Select &s) {
        auto sp = make_shared<Entity>(Entity{});
        sp->select_setter(s);
        return sp;
    }
};

此塊演示了我希望如何使用Entity類型:

int main() {
    auto sp = Entity::create({1, 1});    
    sp->select_setter({2, 2});
    sp->select_setter({3, 3});    
    cout << "the end" << endl;
    return 0;
}

這是輸出:

destroying 00
to be assigned... 11
destroying 11
to be assigned... 22
destroying 22
to be assigned... 33
destroying 33
the end
destroying 33

為什么33被摧毀兩次,但00,11和22只被摧毀一次?

當你想分析這樣的構造函數/析構函數行為時,我的建議是:

  • 記錄所有構造函數(默認構造函數,復制構造函數,其他構造函數)
  • 記錄所有析構函數
  • 知道誰是誰的對象的日志地址......

通過添加更多輸出,並實現SelectEntity復制構造函數,您可以獲得:

Before auto sp = Entity::create({1, 1});
In Select 1 1 ctor 0x7fff85e31b80                    // That's Select temporary object {1,1} being created
In Select default ctor 0x7fff85e31b40                // That's Entity attribute being created before Entity ctor is entered below
In Entity ctor 0x7fff85e31b40                        // That's Entity ctor for Entity{} you create
In Select default ctor 0x2248028                     // That's Entity attribute being created before Entity ctor is entered below
In Entity copy ctor copy 0x7fff85e31b40 to 0x2248028 // That's copying Entity{} object as the shared_ptr attribute
In Entity dtor 0x7fff85e31b40                        // That's Entity{} being destroyed
destroying 00 0x7fff85e31b40                         // That's Entity{}'s Select attribute being destroyed. Is 00 but could be anything else (not initialized)
to be assigned... 11
destroying 11 0x7fff85e31b80                         // That's Select temporary object {1,1} being destroyed

Before sp->select_setter({2, 2});
In Select 2 2 ctor 0x7fff85e31b70                    // That's Select temporary object ({2,2})
to be assigned... 22
destroying 22 0x7fff85e31b70                         // That's Select temporary object ({2,2}) being destroyed

Before sp->select_setter({3, 3});
In Select 3 3 ctor 0x7fff85e31b80                    // That's Select temporary object ({3,3})
to be assigned... 33
destroying 33 0x7fff85e31b80                         // That's Select temporary object ({2,2}) being destroyed

the end
In Entity dtor 0x2248028                             // That's Entity stored in the shared_ptr object being destroyed
destroying 33 0x2248028

這完全有道理......

只需使用此代碼:

#include <memory>
#include <iostream>
using namespace std;

class Select {
    int i, j;

    friend class Entity;

public:
    Select(int a, int b) : i{a}, j{b} { std::cout << "In Select " << a << " " << b << " ctor" << std::hex << "0x" << this << std::endl;}

    ~Select() {
        cout << "destroying " << i << j << std::hex << "0x" << this << endl;
    }

    Select( const Select& e ) {
        i = e.i; j = e.j;
        std::cout << "In Select copy ctor copy " << std::hex << "0x" << &e << " to " << std::hex << "0x" << this << std::endl;
    }

    Select() { std::cout << "In Select default ctor" << std::hex << "0x" << this << std::endl; }

};

class Entity {

    Select select_;

public:

    Entity() { std::cout << "In Entity ctor " << std::hex << "0x" << this << std::endl; }
    Entity( const Entity& e ) {
         select_ = e.select_;
         std::cout << "In Entity copy ctor copy " << std::hex << "0x" << &e << " to " << std::hex << "0x" << this << std::endl;  }

    ~Entity() { std::cout << "In Entity dtor " << std::hex << "0x" << this << std::endl; }

    void select_setter(const Select &select) {
        cout << "to be assigned... " << select.i << select.j << endl;
        select_ = select;
    }

    static shared_ptr<Entity> create(const Select &s) {
        auto sp = make_shared<Entity>(Entity{});
        sp->select_setter(s);
        return sp;
    }
};

int main() {
    std::cout << "Before auto sp = Entity::create({1, 1});" << std::endl;
    auto sp = Entity::create({1, 1});
    std::cout << "Before sp->select_setter({2, 2});" << std::endl;
    sp->select_setter({2, 2});
    std::cout << "Before sp->select_setter({3, 3});" << std::endl;
    sp->select_setter({3, 3});
    cout << "the end" << endl;
    return 0;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM