我正在研究一个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只被摧毁一次?
答案 0 :(得分:3)
当你想分析这样的构造函数/析构函数行为时,我的建议是:
通过添加更多输出,并实施Select
和Entity
副本构造函数,您可以获得:
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;
}