unnecessary dynamic memory allocation

The idea of this thread is to serve as a reference to link when spotting a T *foo = new T; or similar code snip.

It may also include some misconceptions that propitiate the use of such aberration (like the ignorance on initialization list, java background, declaring a function instead of an object)


delete new T
Last edited on
Why not write an article?
Bjarne Stroustrup wrote:
Code that creates an object using new and then deletes it at the end of the same scope is ugly, error-prone, and inefficient.

ugly:
Gadget *p = new Gadget(n);
[sarcasm] c++ is so stupid that you need to tell it twice what you want [/sarcasm]

error prone:
1
2
3
4
5
6
7
8
void foo(int n, int x){
   Gadget *p = new Gadget(n);
   //...
   if(x<100) throw std::run_time_error("weird"); //leak
   if(x<200) return; //leak
   //...
   delete p; //may as well forget this
}


inefficient:
1
2
3
4
5
6
7
void foo(int n, int x){
   unique_ptr<Gadget> p = new Gadget(n); //managing that pointer
   //...
   if(x<100) throw std::run_time_error("weird"); //no leak
   if(x<200) return; //no leak
   //...
}
- one extra indirection
- cache misses
- dynamic allocation is expensive


Gadget p(n); //yay
Last edited on
> Why not write an article?
because this way I can have the beautiful feedback of the community.

And better than feedback, they could contribute too (as if I'm qualified at all)
> Foo bar(); doesn't work
http://www.parashift.com/c++-faq/empty-parens-in-object-decl.html


> I can't construct my member variables if I don't use a pointer
Check out initialization list
> Foo bar(); doesn't work

That's why you should use Foo bar{};
Or Foo bar;

As in:

1
2
3
4
string  why;
int     distrupt;
char    this_;
MyClass pattern;
Last edited on
> Or Foo bar;

Foo bar ; and Foo bar{} ; are not equivalent.

1
2
3
4
5
Foo bar ; // bar is default initialized 
// http://en.cppreference.com/w/cpp/language/default_initialization

Foo bar{} ; // bar is value initialized 
// http://en.cppreference.com/w/cpp/language/value_initialization 
Foo bar ; and Foo bar{} ; are not equivalent.


For classes, they should be. Unless the class is extremely poorly designed.

That's like saying bar += 5; is not the same as bar = bar + 5;. They could be different... but usually they're not.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
#include <array>

int main()
{
    std::array<int,12> value_initialized{} ;
    std::cout << "value_initialized: " ;
    for( int i : value_initialized ) std::cout << i << ' ' ; // 0 0 0 0 0 0 0 0 0 0 0 0
    std::cout << '\n' ;

    std::array<int,12> default_initialized ;
    std::cout << "default_initialized: " ;
    for( int i : default_initialized ) std::cout << i << ' ' ; // undefined behaviour
    std::cout << '\n' ;
}

http://coliru.stacked-crooked.com/a/4594e52716b23059
Yes. std::array is quite possibly the one and only exception. And that's only because it's designed to function like a lightweight array and not an encapsulated class.

(and yes, I'm aware that basic types like int also behave differently in this case)

On the other hand:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// These are the same:
std::string a;
std::string b{};

// So are these:
std::vector<int> a;
std::vector<int> b{};

// And these:
wxWindow a;
wxWindow b{};

// And these:
sf::Sprite a;
sf::Sprite b{};

// And these:
AnyClassIveEverWritten a;
AnyClassIveEverWritten b{};

// the list goes on, and on, and on 



EDIT:

To clarify:

Technically you're right. Value initializing and default initializing are different things. I'm not saying you're wrong.
Last edited on
Registered users can post here. Sign in or register to post.