C++ 中动态值的清晰映射
Clear map of dynamic values in C++
我看到很多网站都在讨论为 class 包含地图的对象实施 d'tor 的正确方法。
但不适用于动态分配地图本身的值的情况。
例如,设 Manager
是一个 class,其中包含 map<int, User*>
,其中 User
是一些 class,稍后我将动态分配。
根据练习规则,它应该处理一个 registerUser(string name)
函数,该函数创建一个新的 User
实例并将其添加到地图中。
类似于:
User* registerUser(std::string userName) {
User* pNewUser = new User(userName);
// Setting some stuff
auto ret = users.insert(std::pair<int, User*>(pNewUser->id, pNewUser));
// Finishing and returning a pointer to the new allocated User
}
以及问题本身:
d'tor 是否应该做一些超越 users.clear()
的特别事情?
是内存释放成功还是遍历元素删除?
提前谢谢你:)
不必要时不要使用指针。 std::map
已经为您管理其元素的生命周期:
struct User {
std::string name;
int id;
static int id_counter;
User(const std::string& name) : name(name),id(id_counter++) {}
};
struct manager {
std::map<int,User> users;
User& registerUser(std::string userName) {
User u(userName);
auto ret = users.emplace(u.id,u);
return ret.first->second;
}
};
如果你因为奇怪的不切实际的练习要求(或者因为地图应该保存多态对象)而被迫使用 std::map<int,User*>
并且你不能使用智能指针,那么你需要 delete
你 new
编辑了什么。地图只管理它的元素,而不是它们可能指向的内容:
struct manager {
std::map<int,User*> users;
User& registerUser(std::string userName) {
User* u = new User(userName);
auto ret = users.emplace(u->id,u);
return *(ret.first->second);
}
~manager() {
for (const auto& user : users){
delete user.second;
}
}
// the compiler generated assignment and copy would not do the right thing
manager(const manager&) = delete;
manager& operator=(const manager&) = delete;
};
不确定您从哪里读到有关持有 map
成员并需要致电 clear()
的信息。那是胡说八道。 map
有一个自动调用的析构函数,地图确实已经自行清理。
最后但同样重要的是,您需要阅读有关 3 的规则(What is The Rule of Three?), because a destructor alone is not sufficient to correctly manage raw pointers as members. As mentioned in a comment, when you copy the manager
via the compiler generated copy constructor or assignment, bad things will happen. Note that this isnt the case with the first version above. When possible you should try to follow the rule of 0 (https://en.cppreference.com/w/cpp/language/rule_of_three 向下滚动)。
d'tor 是否应该做一些超越 users.clear()
的特别事情?
一般来说,这取决于您的代码如何处理堆分配对象的所有权;任何时候你通过 new
调用构造函数(也就是在堆上分配)你应该是代码中的一个 ware of wich 组件拥有新创建的对象的所有权,因此负责删除对象。
对于这个特定的玩具问题,您的 Manager
class 还应该通过以您喜欢的方式遍历所有元素并调用 delete
来处理对象的删除。是一个ware 一些其他组件仍然可以保留这些 User
指针之一,这将在最好的情况下通过访问 无效内存 和 运行 很好,直到它在最坏的情况下发货(或启动核 war,因为这在 未定义行为 的范围内)。最先进的解决方案是使用某种智能指针。
当然, 在他的回答中说得非常好,你不需要打电话给 users.clear()
。由于 map
将被自动删除,因为它是一个静态分配的变量 (但不一定是 map
的内容).
我看到很多网站都在讨论为 class 包含地图的对象实施 d'tor 的正确方法。 但不适用于动态分配地图本身的值的情况。
例如,设 Manager
是一个 class,其中包含 map<int, User*>
,其中 User
是一些 class,稍后我将动态分配。
根据练习规则,它应该处理一个 registerUser(string name)
函数,该函数创建一个新的 User
实例并将其添加到地图中。
类似于:
User* registerUser(std::string userName) {
User* pNewUser = new User(userName);
// Setting some stuff
auto ret = users.insert(std::pair<int, User*>(pNewUser->id, pNewUser));
// Finishing and returning a pointer to the new allocated User
}
以及问题本身:
d'tor 是否应该做一些超越 users.clear()
的特别事情?
是内存释放成功还是遍历元素删除?
提前谢谢你:)
不必要时不要使用指针。 std::map
已经为您管理其元素的生命周期:
struct User {
std::string name;
int id;
static int id_counter;
User(const std::string& name) : name(name),id(id_counter++) {}
};
struct manager {
std::map<int,User> users;
User& registerUser(std::string userName) {
User u(userName);
auto ret = users.emplace(u.id,u);
return ret.first->second;
}
};
如果你因为奇怪的不切实际的练习要求(或者因为地图应该保存多态对象)而被迫使用 std::map<int,User*>
并且你不能使用智能指针,那么你需要 delete
你 new
编辑了什么。地图只管理它的元素,而不是它们可能指向的内容:
struct manager {
std::map<int,User*> users;
User& registerUser(std::string userName) {
User* u = new User(userName);
auto ret = users.emplace(u->id,u);
return *(ret.first->second);
}
~manager() {
for (const auto& user : users){
delete user.second;
}
}
// the compiler generated assignment and copy would not do the right thing
manager(const manager&) = delete;
manager& operator=(const manager&) = delete;
};
不确定您从哪里读到有关持有 map
成员并需要致电 clear()
的信息。那是胡说八道。 map
有一个自动调用的析构函数,地图确实已经自行清理。
最后但同样重要的是,您需要阅读有关 3 的规则(What is The Rule of Three?), because a destructor alone is not sufficient to correctly manage raw pointers as members. As mentioned in a comment, when you copy the manager
via the compiler generated copy constructor or assignment, bad things will happen. Note that this isnt the case with the first version above. When possible you should try to follow the rule of 0 (https://en.cppreference.com/w/cpp/language/rule_of_three 向下滚动)。
d'tor 是否应该做一些超越 users.clear()
的特别事情?
一般来说,这取决于您的代码如何处理堆分配对象的所有权;任何时候你通过 new
调用构造函数(也就是在堆上分配)你应该是代码中的一个 ware of wich 组件拥有新创建的对象的所有权,因此负责删除对象。
对于这个特定的玩具问题,您的 Manager
class 还应该通过以您喜欢的方式遍历所有元素并调用 delete
来处理对象的删除。是一个ware 一些其他组件仍然可以保留这些 User
指针之一,这将在最好的情况下通过访问 无效内存 和 运行 很好,直到它在最坏的情况下发货(或启动核 war,因为这在 未定义行为 的范围内)。最先进的解决方案是使用某种智能指针。
当然,users.clear()
。由于 map
将被自动删除,因为它是一个静态分配的变量 (但不一定是 map
的内容).