简体   繁体   中英

Fields within dynamically allocated objects - better dynamically or statically allocated? C++

I know it's basic question but I'm quite new to C++ and I'd like to know if for example I have 2 classes:

class MyClass1 {
private:
    vector<int> iVals;
    std::string name;
public:
    MyClass1(std::string name) {
        this->name = name;
    }
    ~MyClass1() {
        //empty
    }
};

class MyClass2 {
private:
    vector<int>* iVals;
    std::string* name;
public:
    MyClass2(std::string name) {
        this->iVals = new vector<int>();
        this->name = new std::string(name);
    }
    ~MyClass2() {
        delete this->iVals;
        delete this->name;
    }
};

Instances of both classes I can initialize statically or dynamically in main() method

int main() {
    MyClass1 c_1("one");
    MyClass1* c_11 = new MyClass1("one one");
    MyClass2 c_2("two");
    MyClass2* c_22 = new MyClass2("two two");
}

My question is what is better way to implement such classes? With "static"(no the static keyword) or dynamic fields?

If I do

MyClass1* c_11 = new MyClass1("one one");

If I'm correct, objects fields, which are not allocated dynamically, will be allocated also on heap. So is there any practical reason to allocate any class member dynamically?

While there is sometimes a use for dynamically allocated members (I basically use them for polymorphic members and that's about it), I would not use it like you implemented MyClass2 . This has many possibilities for bugs, the foremost (in my opinion) beeing:

You did not define a copy/move constructor and copy/move assignment. The implicit constructors would only work on the value of the pointer and not the object it's pointing to. So if you have MyClass2 a("Hi"); MyClass2 b = a; MyClass2 a("Hi"); MyClass2 b = a; both of them would point to the same std::string . If one goes out of scope, this object is deleted and the other pointer is dangling. Hence, we have the so called rule of five .

Hence, if you have an object owning memory, you should use std::unique_ptr . It is a wrapper around a pointer, which deletes it if the object is deleted. Due to this the default constructors and deleter work perfectly well and you dont have to worry at all about managing the memory. All of this comes with minor runtime overhead.

If you come to the point, where multiple objects share some memory and you cannot say that one of those outlives all others, working with raw pointers becomes very troublesome. Then you should look at std::shared_ptr . But be careful, it is easy to get a hefty overhead if not used in the right way.

It is ok to use raw pointers if you just want to look at an object or modify it and are absolutely sure that the object pointed to will not get deleted while doing so. But having raw new and delete in your code should always make you think whether it is really needed.

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