简体   繁体   中英

C++:using pointer to unordered_map or just defining it as a member variable from this type in a class?

I have a problem which I cannot understand:

Let's Say I have a class System with several member fields, and one of them is of type unordered_map , so when I declare the class in the header file, I write at the beginning of the header #include <unordered_map> .

Now, I have two ways of declaring this field:

1.std::unordered_map<std::string,int> umap;
2.std::unordered_map<std::string,int>* p_umap;

Now in the constructor of the class, if I choose the first option, there is no need to initialize that field in the initializer list since the constructor of class System will call the default constructor for the field umap as part of constructing an instance of type class System .

If I choose the second option, I should initialize the field p_umap in the constructor (in the initialize list) with the operator new and in the destructor, to delete this dynamic allocation.

What is the difference between these two options? If you have a class that one of it's fields is of type unordered_map , how do you declare this field? As a pointer or as a variable of type unordered_map ?

In a situation like the one you are describing, it seems like the first option is preferable. Most likely, in fact, the unordered map is intended to be owned by the class it is a data member of. In other words, its lifetime should not be extended beyond the lifetime of the encapsulating class, and the encapsulating class has the responsibility of creating and destroying the unordered map.

While with option 1 all this work is done automatically, with option 2 you would have to take care of it manually (and take care of correct copy-construction, copy-assignment, exception-safety, lack of memory leaks, and so on). Surely you could use smart pointers (eg std::unique_ptr<> ) to encapsulate this responsibility into a wrapper that would take care of deleting the wrapped object when the smart pointer itself goes out of scope (this idiom is called RAII, which is an acronym for Resource Acquisition Is Initialization ).

However, it seems to me like you do not really need a pointer at all here. You have an object whose lifetime is completely bounded by the lifetime of the class that contains it. In these situations, you should just not use pointers and prefer declaring the variable as:

std::unordered_map<std::string, int> umap;

Make it not a pointer until you need to make it a pointer.

Pointers are rife with user error.

For example, you forgot to mention that your class System would also need to implement

System( const Sysytem& )

and

System& operator= ( const System& )

or Bad Behavior will arise when you try to copy your object.

The difference is in how you want to be able to access umap. Pointers can allow for a bit more flexibility, but they obviously add complexity in terms of allocation (stack vs heap, destructors and such). If you use a pointer to umap, you can do some pretty convoluted stuff such as making two System's with the same umap. In the end though, go with KISS unless there's a compelling reason not to.

There is no need to define it as pointer. If you do it, you must also make sure to implement copy constructor and assignment operator, or disable them completely.

If there is no specific reason to make it a pointer (and you don't show any) just make it a normal member variable.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM