#Purpose of dynamically allocating things

1 messages · Page 1 of 1 (latest)

tranquil moss
#

Coming from c, I would use dynamic allocation if i wanted a variable to outlive the scope of the array, prevent things like dangling pointers, and creating arrays with a size that isnt know during run time. In C++ i learned, there is no reason to dynamically allocate an array because in that case you would just use a vector, other than having things outlive the scope, is there any other use for dynamic allocation in c++?

cobalt gateBOT
#

When your question is answered use !solved to mark the question as resolved.

Remember to ask specific questions, provide necessary details, and reduce your question to its simplest form. For tips on how to ask a good question use !howto ask.

junior dirge
#

dynamic allocation is useful for smart pointers and creating new containers... other than that personally i would avoid dynamically allocating memory

#

if you want something to exist beyond a scope that's still possible through smart pointers, and even than since those objects can be destroyed when out of scope it makes managing that dynamically allocated memory much much easier

#

and less error prone

calm sapphire
obtuse umbra
calm sapphire
obtuse umbra
#

Sure its bigger but that isnt the only property that distinguishes the two

#

Any resource that does not fall into the category of automatic storage duration should be allocated dynamically

lunar sequoia
#

Where did you get the "use vector instead of dynamic allocation"? It's true vectors provide a convenient way of dealing with dynamic arrays, and even allowing the size to change with automatic reallocations, but it's far from a universal solution. Also to keep in kind, even though vectors use dynamic allocation in the backend, the vector itself is still on the stack by default and needs to remain in scope, otherwise its allocation is also deleted. So you neither can't just pass around a vector pointer or a value, as passing the value will copy all items in most cases.

feral badger
#
struct vector{
/* bunch of member functions */
private:
  T* data;
  size_t siz;
  size_t cap;
};

this is esentially what a vector is.

tranquil moss
tranquil moss
#

So would there be cases where I need to dynamically allocate a std::array or std::vector then

tranquil moss
feral badger
#

"copy semantics" is just a constructor call that copies the array element by element

#
//disregard capacity for now
vector::vector(const vector& other) : data(new T[other.siz]), siz(other.siz) {
  std::copy(other.data, other.data+other.siz, data);
}
#

this is just how vector is copied

#

there is no magic

#

its the same as C

tranquil moss
#

Sorry I meant move semantics

feral badger
#

just abstracted away so you dont see

junior dirge
feral badger
#

you can implement your own containers bing_shrug

junior dirge
#

Vector handles that and you can handle its lifetime in a manner less error prone

tranquil moss
#

When I went over learncpp it said that the move semantics for vectors are actually not expensive so we can just return them

tranquil moss
feral badger
junior dirge
#

Not unless you copy tje wjole tjing

feral badger
junior dirge
#

Like maps, stacks etc

tranquil moss
#

Oh okay yeah

tranquil moss
feral badger
junior dirge
feral badger
#

the purpose is that you wouldnt have vector and other stuff like it without dynamic allocation

junior dirge
#

You are copying its entire contents if you pass it by value to a function if i remember correctly

tranquil moss
#

But it’s all abstracted away in Cpp, so the only time I’d use it is if I were to make my own container then?

feral badger
junior dirge
#

yes

tranquil moss
junior dirge
#

Irrelevant

junior dirge
#

Idk man i dont use move sementics 😭😭😭

feral badger
tranquil moss
#

Use them for what?

feral badger
#

vector uses dynamic allocations

tranquil moss
#

but I was asking about manually allocating things

feral badger
#

i genuinely dont understand the point of the thread tbf

tranquil moss
#

A vector hides the dynamic allocation part

feral badger
#

every language that wants to do anything significant needs some kind of dynamic allocation

junior dirge
#

Hes asking som bout manually allocating things vs using containers to do it for u

junior dirge
#

It handles it for you

feral badger
junior dirge
#

thats why you should use it over making your own

tranquil moss
#

Yes so I was just asking about what case would I have to manually allocate stuff

tranquil moss
#

If things like vectors already handle it

feral badger
#

hopefully never!

tranquil moss
#

Unlike in c where you have to manually allocate arrays since you don’t have things like vectors

feral badger
#

i mean if you consider std::make_unique a dynamic allocation then there is that

junior dirge
#

Like i said bud, you ideally dont have to unless you are making your own containers 🥺🥺🥺

feral badger
feral badger
junior dirge
#

Or like making smart pointers, which require an address on heap/ given by new

#

Sometimes

feral badger
#

no point in writing a lot of abstractions in C because you still have to manually reallocate, allocate, free the array

tranquil moss
#

Would be used for polymorphism as well? Or do you not need to use new for polymorphism

junior dirge
#

Real

feral badger
#

c++ gives you destructors which is a C programer's wet dream

feral badger
junior dirge
feral badger
tranquil moss
#

Has to be a pointer to the base class no?

feral badger
junior dirge
#

base* can

#

Fuck

feral badger
#

unique_ptr<Base>

junior dirge
#

Beat me to it

feral badger
#

:)

junior dirge
#

So what, vector<unique_ptr<base>>

feral badger
feral badger
tranquil moss
#

So I would have to just give it a pointer to the derived object?

junior dirge
#

Ok

tranquil moss
#

Doesn’t matter if it’s on stack or heap?

feral badger
junior dirge
#

For vector

#

base* can be stack and heap

#

But required your own management of it

feral badger
#

its basically

class unique_ptr{
  T* ptr;
public:
  unique_ptr(T* ptr) : ptr(ptr) {}
  ~unique_ptr(){
    delete ptr;
  }
};
junior dirge
#

Essentially becomes a shitier smart pointers atp prob

feral badger
junior dirge
#

So once unique ptr goes out of scope or is deleted its feed

feral badger
#

that will cause a use after free bug

#
int x = 5;
std::unique_ptr<int> ptr(&x);
//ptr destructor calls delete &x;
//x is "freed" again due to it being an automatic lifetime variable
tranquil moss
#

How would I use unique ptr for this? Just learned about it, whenever I see poly morphism examples they either just use a reference or a pointer ie.

Base& x{derived}
//or
Base* x{&derived}
junior dirge
#

Idk maybe there is a wrapper for unique pointers that works with both stack/heap

feral badger
tranquil moss
#

Oh lol

feral badger
junior dirge
#

real

tranquil moss
junior dirge
#

Nuh uh

#

because unless it has an overload constructor for that type it should fail

tranquil moss
#

Oh did not know that

junior dirge
#

Compile it

#

Im on mobile

tranquil moss
#

When I first learned about polymorphism people just used new, so they’d do:

Base* x = new Derived;

So it just made me wonder whether or not poly morphism needs to work with dynamically allocated memory or not

junior dirge
#

It doesnt

tranquil moss
#

Like if it would break somewhere down the line if I used it with an automatically managed object

#

Oh

junior dirge
#

a pointer is a pointer doesnt matter if its heap or stack

#

What changes is its lifetime and how much is allocated for that address

#

even than… the amount allocated for the address is stored at compile time per address for stack… the program just knows which address+ offset is for which variable… the heap is programatic unlike stack

#

but thats a bit advanced.. only useful in assembly land where you manually have to subtract anf increment the stack and manually remember which offset at rsp is for which variable

#

Its thr fact that you have to read addresses + offsets at the top of rsp register (which is stack) that makes it so rigid. Maybe you should learn more about stack frames and how stack is allocated and maintained in assembly/C, it could be informative to you

#

Pretty good video.. always seek the knowledge 🥴🥴🥴

tranquil moss
#

Oh yeah idk why I got confused lol. I’ve been transitioning to c++ from c and classes just trip me up and C++ making things easier just tickles my brain

tranquil moss
#

Just curious since we’re on the topic

#

One of the lessons on Learn Cpp says that if I have a base and derived, and I dynamically allocate the derived into the base ie. Base *x{new derived}. Then I need to make the base destructor virtual so that the derived constructor is called first then the base but I’m confused because when we do the constructors we don’t make them virtual but it would call the base constructor then the derived. Whys it different?

lunar sequoia
#

In the line 'Base* base = new Derived();` you're explicitly calling the derived constructor after allocating it on the heap. However if you store it as a bass class pointer, the compiler is only aware of the destructor for the pointer type, as that's what is fixed at compile-time. By making the destructor a virtual function, you force the call to go through the v-table like any other virtual function. Since you used the Derived constructor, the v-table pointer will also point to Derived, including the address of the Derived destructor

tranquil moss
limpid vigil
#

Yes. However, when you call new Derived() you're explicitly constructing a derived, and then you store that derived in a Base pointer. So when you call the constructor, it knows that you're constructing a Derived and it knows to call the Derived constructor after the Base constructor. Ones its put into the Base* however, it no longer knows that its a Derived, it just knows that you have something that has the same interface as a Base. Thus, any function calls will only go down to the Derived if they're over-writing virtual functions.

#

Some other notes on this thread generally:
You use dynamic allocation if the size of something isn't known at compile time or if you need to manage the length something exists for. In modern C++, you'll never use raw dynamic allocation, you'll either use smart pointers (Unique/Shared) for managing lifetimes or some STL container (vector, list) for managing size at runtime.

In the case of polymorphism, smart pointers are used if you're not sure what type you're going to be allocating at compile time, so you can generate and store pointers to derived types as a base type at runtime.

Move semantics are complex beast. Essentially, its safe to return a vector from a function as that will avoid a copy, since the returned value is an rvalue and the = operator or constructor will use the move variant, and move the underlying data pointer rather than copying the data. When passing values to functions, you should be using reference for non-primitive types (STL types, custom objects) to avoid copies (IE pass std::string& str instead of std::string str.

lunar sequoia
#

For the last part, prefer adding const before type& unless you absolutely need to mutate the object within the function. Not only does that allow passing const objects, but more importantly it allows creation within the call. For instance, you can "Hello World" as a const std::string& but not if the parameter is std::string&

willow mist
#

Oh and try to avoid smart pointer magic while learning the basics, cause, they are complicated, you must come prepared with knowledge about the C++ language rules first

feral badger
#

Also when returning a local variable, there will be a move most likely, not a copy

#

No reason to copy if the local is destroyed afterwards anyways

willow mist
feral badger
#

Gcc actually has a warning where it failed to apply rvo which is cool