gpt4 book ai didi

c++ - 销毁顺序和赋值

转载 作者:行者123 更新时间:2023-11-30 02:31:32 25 4
gpt4 key购买 nike

我正在处理一个 Entity 类,它需要通过 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;
}
};

此 block 演示了我希望如何使用 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;
}

关于c++ - 销毁顺序和赋值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37513412/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com