* New is always wrong. ALWAYS

To explain about pointers and links in this question , I wrote this code.

MyClass& MyClass::MyInstance() { static MyClass & myLocalVariable = * new MyClass(/*parameters*/); return myLocalVariable ; } 

One of the comments, a really impressive SO high reputation user, simply states: * The new is always wrong. ALWAYS.

This is the first time I have been told about this: is it a well-known coding standard that we should all be aware of? What are the reasons?

+7
c ++
source share
5 answers

I'm usually pragmatic, but it's too much for me!

 static MyClass & myLocalVariable = * new MyClass(/*parameters*/); 

Seriously? Why not just:

 static MyClass myLocalVariable{/*parameters*/}; 
+9
source share

The most obvious reason is that if you do not save a copy of the pointer that was returned, you are unlikely to ever call delete on it.

On a more human level, this will make people reading your code think less about you, which is also not very good.

+3
source share

I believe that the claimed user meant that allocating a static object using a new one is dangerous, as memory is likely to leak. More importantly, your variable is not a pointer, but a link, so the likelihood that you will never free the memory returned by the new one is even greater (how often do you delete the address of the link?).

0
source share

The problem is more than just useless distributions.

If no one causes a deletion on it, it will not be deleted. Of course, the memory will be released when the program ends, but its destructor will not be called.

Compare the result of using Get() and Get2() in the code below:

  #include <iostream> struct A { ~A(){std::cout << "Deleted\n";} }; A& Get() { static A & a = *new A; return a; } A& Get2() { static A a; return a; } int main() { //Case 1 Get(); //Case 2 Get2(); } 

The exit of this program when calling Get and Deleted when calling Get2 does not cause anything. In other words, resources with non-trivial destructors (for example, using the commit-on-close file) will not be destroyed properly when the program terminates in case 1, but in case 2.

0
source share

The problem is that raw new does not define ownership. If I am new to the object and return it, to whom does it belong? Does it create a function / object or perform a call function? If you return smart pointers (std :: shared_ptr and std :: unique_ptr), you specify ownership.

Not specifying ownership is one of the easiest ways to leak memory. It’s the hardest part for me, even with professional programmers, forcing people to understand property and work with it. This is largely prevented by using good types (smart pointers) that define ownership only by existing.

 type* function(); // Unspecified ownership. // Must be well documented and all users must read // and follow the documentation. std::unique_ptr<type> function(); // Calling function owns returned pointer. // Single ownership. std::shared_ptr<type> function(); // Calling function owns returned pointer. // Shared ownership. Can have multiple owners. std::weak_ptr<type> function(); // Calling function references returned pointer. // Must lock pointer to get owned object, if not deleted. // Shared ownership. Can have multiple owners. 

These various types of pointers express ownership of existing ones only, unlike original pointers.

As for new , always wrong. This is an excessive generalization. std::shared_ptr is created using the global function std::make_shared . Starting with C ++ 11 there is no std::make_unique , but this will be fixed in C ++ 14. The only way to create std::unique_ptr is to use the new one and immediately assign a pointer to std::unique_ptr .

There are also places where you need a raw pointer and manually use new and delete , but they are usually very low, and most programmers rarely come across them.


Which really annoys me is your code, not that you are using new , but you are looking for a pointer and assigning it a link. It would be almost impossible to guarantee that the destructor would ever be called. It also tends to leak memory, although if a static variable is assigned, it will be freed when the program terminates, so you really don't look at a memory leak.

 MyClass& MyClass::MyInstance() { static MyClass & myLocalVariable = * new MyClass(/*parameters*/); return myLocalVariable ; } 

I would prefer to create a static variable by value, not by reference. This prevents the object from being placed in a heap. Depending on MyClass , you can also enable the mapping of an object into memory from an executable file without the need to run any code to initialize it.

 MyClass& MyClass::MyInstance() { static MyClass myLocalVariable(/*parameters*/); return myLocalVariable ; } 
0
source share

All Articles