#Object Ownership

176 messages · Page 1 of 1 (latest)

nocturne garnet
#

Currently I have an asset class and an asset manager. When I run the constructor I basically want to force where the object is created. I know I can't just "override" what the new operator returns, and I don't want to have to create a static function by hand for each different type of asset. I'm thinking some sort of preprocessor macro that can do that for me.. the variable amount of arguments and such.

bitter urchinBOT
#

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 more information use !howto ask.

nocturne garnet
#

I come from C# and had really no concept of object ownership.

#

I think the best option I have is to create a static function that return a unique pointer

#

Thing is: I dont know if its possible to automate this whole process with macros.

livid sable
#

why do u specifically think that preprocessor would be the solution? this sounds like a xy problem to me. why not just use what the language wanta u to use naturally

nocturne garnet
#

i want to be able to get into the nitty gritty optimizations

livid sable
#

for example if u want to own sth and want it to be on heap, create a unique_ptr

nocturne garnet
#

really i just want to be able to return a shared pointer in the constructor

livid sable
#

why the need to externalize that

livid sable
nocturne garnet
#

it just doesnt feel intuitive to do make_shared<T>(arg)

#

unlike T* x = new T()

livid sable
#

why? u don't like the syntax?

#

its feels very natural to all cpp devs

nocturne garnet
#

its not that i dont like the syntax

#

it just feels off, at least coming from c#

livid sable
#

why did u write x there though

#

u want perfect forwarding

#

std::make_shared<Person>("john", 20)

#

i know it feels off coming from c# but its the proper cpp way

latent canopy
#

why do you think you want a shared_ptr?

livid sable
#

in modern cpp u rarely call a constructor directly

nocturne garnet
#

when i use raw pointers all my experienced c++ pals are cringing at the sight

#

if my vector of assets changes length

#

something gets deleted i have a dangling polinter

livid sable
#

bc u shouldn't use raw ptrs

latent canopy
#

yeah but then use unique_ptr or smth

#

also, there's not necessarily anything wrong with raw pointers

livid sable
#

the question is why shared ptr specifically. do u want to share ownership?

latent canopy
#

depends on the context

nocturne garnet
#

well coming from c# i have the garbage collector

#

when its not referenced it gets deleted

#

ig im aiming for that

latent canopy
#

then you should use C#

#

C++ isn't programmed like that

#

it just works differently

nocturne garnet
#

I understand, but like I said I want to get into the nitty gritty

livid sable
#

the c# behavior is shared ptr in cpp. but u should go beyond that and increase ur horizon

latent canopy
#

C++ has deterministic object lifetime, which you can use to automate resource management

latent canopy
nocturne garnet
#

having control of what happens and when

latent canopy
#

and you think the way to do that is to try as hard as you can to not do anything different from how you did things in C#? 😛

nocturne garnet
#

no : (

livid sable
#

as u figured, in cpp u can give more control over lifetime and ownership. more than in c#.
if u want that sth is only owned by one guy, make it unique_ptr

nocturne garnet
#

is there a way to check with unique ptr if its invalid

livid sable
#

if u want it to be shared, shared_ptr.
if u want it to not be owning but claim ownership in the future, weak_ptr

livid sable
#

the same way as with the rest

#

if (ptr)

latent canopy
#

if you're coming from C# and are trying to pick up C++, i recommend that you read a good C++ beginner's book. C++ is a fundamentally different language from C#. you're going to need to get a lot of fundamentals straight in order to use C++ effectively.

livid sable
#

or if(ptr != nullptr)

#

both do the same

nocturne garnet
#

i get pointers and stuff, the hurdles are just fundamental program design differences

latent canopy
#

but as a general rule of thumb: if you're reaching for shared_ptr, you're probably doing smth wrong.

livid sable
#

a lot of things translate well. it's mostly about the ownership topic thats just fundamentally different

nocturne garnet
#

ok: )

livid sable
#

cause c# just doesnt bother with that

latent canopy
#

well, you're probably familiar with using blocks in C#

nocturne garnet
livid sable
#

so learn ur options and then use what is appropriate to express ur intentions

nocturne garnet
#

though obv i was really limited w/ what i could do

latent canopy
#

a key thing to understand is constructors and destructors and when and how they're called.

#

everything to do with lifetime builds on that

nocturne garnet
#

lifetime: stack when out of scope

#

heap when delete

latent canopy
#

and value semantics

#

that's also gonna be a big one i guess, coming from C#

livid sable
#

for most of ur basic needs, they replace raw pointers

nocturne garnet
#

how exactly would i implement this

latent canopy
#

well, the thing is, ideally, you'd just not use any of that and allocate stuff on the stack and stuff

#

dynamic allocation is for those rare circumstances where you actually need it

nocturne garnet
#

cause you cant copy a unique ptr

latent canopy
#

you can move it

livid sable
#

if u want ro transfer ownership of a unique_ptr, u just move it

latent canopy
#

which, again, is smth that builds on those fundamentals we were talking about

#

coming from C#, you're not going to have a good time just jumping right into the middle of C++

livid sable
#

point is, it's still just one guy owning it. but u can freely transfer that around

latent canopy
#

you need to start at the beginning i'm afraid

#

otherwise there will be just confusion and more confusion

nocturne garnet
livid sable
#

yeah u need to understand what ur expressing and what implications that has

nocturne garnet
#

The more I think about this the more I'm confused honestly

livid sable
#

for example when sth has to be copied

#

or when it can be moved

#

or obsolete due to rvalue

nocturne garnet
#

I have a std::vector of assets, not as a pointer or anything

latent canopy
nocturne garnet
#

raw data in my vector

livid sable
#

then the vector owns those

nocturne garnet
#

i cant have a raw pointer to the object because if the vector changes the pointers become invalid

#

the pointers basically have to track where the data moves

livid sable
#

std::vector<Person> persons means the vector owns the persons and they should be created inside it

nocturne garnet
#

thats how im seeing it

livid sable
#

u can give people a reference if they just want to use it

latent canopy
#

¯_(ツ)_/¯

nocturne garnet
livid sable
#

cpp has so many ways to express ownership, lifetime and all that. its really at the core of everything. each second line of code u write, u have to think about these things

#

better to learn all ur options before going to deep

latent canopy
livid sable
#

value, reference, raw ptr
unique_ptr, shared_ptr, weak_ptr
const
all combinations of above
move, copy, perfect forwarding,...

#

all that stuff u really have to understand before writting more than mini programs

#

also bleeds heavily into the design of classes, including existing classes

#

for example vectors push_back vs emplace_back

#

constructing objects outside of the container, which then have to be moved or copied into it for exclusive ownership, versus constructing them in place

latent canopy
#

tl;dr: C++ is a very complex language and you're really doing yourself no favor by skipping the fundamentals.

livid sable
#

don't worry though. we all had to go through this, it wasnt pleasant until it clicked

#

ull do it to

#

👍

nocturne garnet
#

i wouldnt say i exactly skipped fundamentals

latent canopy
#

yea, not saying that it's hard. it's just smth you gotta do.

nocturne garnet
#

it just hasnt settled

latent canopy
#

k^^

livid sable
#

took me 3 months of active practice until i finally understood what all the textbook definitions actually mean in practice

nocturne garnet
#

right now i havent really even totally settled on a project

#

ive written a few engines in c#, so opengl just makes sense to me

#

ive been just playting around

livid sable
#

unless ur making big projects, i wouldnt worry too much of making mistakes though. it's part of the journey

latent canopy
#

opengl is very tricky since it's very hard to deal with in a classic oop way, dunno i'd recommend that.

#

but i mean, if you're familiar with the API, you can try to write your own RAII wrappers and stuff for it

#

that'd be a place to practise using move semantics yourself

#

which might help a lot with your understanding of it

nocturne garnet
#

ive kinda been screwing around with wrappers

#

never heard of the term RAII though 🤔

latent canopy
#

um ok

#

yet you just told me you didn't skip fundamentals 😛

#

anyways

#

RAII is basically all the stuff we've been talking about

#

it's the idea of using constructors and destructors to automate resource management

#

for example, you'd have a class that represents a buffer object. you'd have a constructor that creates the buffer object. and the destructor would free the buffer object.

#

then you can just go an create instances of that class, which will automatically create a buffer object for you. and they would automatically free the buffer object when the instance is destroyed

livid sable
#

the smart pointers are essentially the implementation of RAII to improve raw ptr usage

nocturne garnet
#

ive just never heard the term before

latent canopy
#

well, that's good then

nocturne garnet
#

im doing exactly that

latent canopy
#

👍

#

then keep doing it

#

now here's where it gets tricky

#

what happens when you copy one of your buffer objects?

nocturne garnet
#

you shouldnt be able to

latent canopy
#

are you able to atm?

nocturne garnet
#

i deleted the copy constructor(s)

#

: )

latent canopy
#

👍

#

the problem with that is that you're now basically stuck with the buffer object in the scope you created it in

#

you can't create a buffer object somewhere and then pass it to someone else to keep

nocturne garnet
#

yeah thats where i was starting to dabble with the asset managers

latent canopy
#

and this is where move semantics come in

nocturne garnet
#

i got past the abstractions stage

latent canopy
#

while you can't copy a buffer object, you can move it

#

i.e., have one buffer object relinquish its ownership of the underlying resource to another one

nocturne garnet
#

i know std::move exists other than that this is completely new

latent canopy
#

yeah

livid sable
#

it's the idea of transfering something from A to B. thats how u can give a unique_ptr to someone else

#

afterwards, A is dead garbage and B contains the moved object

#

that makes it possible for u to give someone who expects a value (=ownership) ur object without a copy. as long as ur willing to give it away forever

nocturne garnet
#

mhm

livid sable
#

let's say u created a method that takes by value:
void foo(Person person)
and u have some person floating around that u want to use

Person person("john");
... 
foo(person);

now that requires a copy. so it will call the copy constructor

#

since u want to own ur person but the method wants to own its parameter as well

#

but if ur willing to sacrifice ur ownership, u can transfer it:
foo(std::move(person))

#

now it doesn't have to create a copy

#

also, when ur giving it a rvalue it also doesnt have to copy it, since ur not holding ownership of rvalues:
foo(Person("john"))

#

and so on

#

there's a lot to learn about all the combinations of value/reference/const and so on

nocturne garnet
#

shows how much i got to learn 😄

#

thanks yall ima close this and get back to learning the fundamentals I guess : )

#

!close

bitter urchinBOT
#

Thank you and let us know if you have any more questions!

#

[SOLVED] Object Ownership