Jump to content

  • Log In with Google      Sign In   
  • Create Account


Assigning A to B without B destroying all the allocations...


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
10 replies to this topic

#1 Waterlimon   Crossbones+   -  Reputation: 2109

Like
0Likes
Like

Posted 03 February 2013 - 11:03 AM

So i have the situation, where i have a class that contains some allocated data (in this case an opengl vertex buffer allocated on the GPU). I have a grid of these objects, and i want to move them all to a bigger grid.
This means doing something along the lines of
bigGrid[x]=smallGrid[x]
that is,
1.A=B
2.~B()
Which is a problem since i have set my vertex buffer deallocate itself upon destruction. How would you recommend me to overcome this problem? Should i use the newish move semantics here?

Thanks

Oh and the original grid is destroyed after copying all of them. So im basically just moving them.

Edited by Waterlimon, 03 February 2013 - 11:10 AM.

The lack of awesome free resource gathering building sandbox games capable of running an user made 8 bit computer in the world disturbs me.

Sponsor:

#2 SiCrane   Moderators   -  Reputation: 9143

Like
1Likes
Like

Posted 03 February 2013 - 11:24 AM

C++11 move assignment would work. Assuming your class implemented the move assignment operator you could invoke it with bigGrid[x] = std::move(smallGrid[x]); Another possibility is to go through and do bigGrid[x].swap(smallGrid[x]) if you implement an appropriate swap() function. How you would implement these would, of course, depend on what your class looks like.

#3 Waterlimon   Crossbones+   -  Reputation: 2109

Like
0Likes
Like

Posted 03 February 2013 - 11:49 AM

The problem is that this copying happens in a template class, so i cant really use a swap...

 

I assume move will work for any type i pass in properly, but will i need to implement the operators required for moving in only the vertex buffer or both the vertex buffer and the class containing it?

 

I read that in some situations on some compilers i would only need to implement it in the vertex buffer but that "some" also means im not going to do that. If this is true, it would be quite inconvenient and i might forget to implement the move for some class in a hierarchy of classes with a vertexbuffer somewhere, resulting in a bug :/

 

Reference counting might be something i can trust but i think that would require allocating the reference count variable which isnt nice.


The lack of awesome free resource gathering building sandbox games capable of running an user made 8 bit computer in the world disturbs me.

#4 Waterlimon   Crossbones+   -  Reputation: 2109

Like
0Likes
Like

Posted 03 February 2013 - 12:23 PM

Never mind, i see you can make an assignment operator without making the parameter const :P


The lack of awesome free resource gathering building sandbox games capable of running an user made 8 bit computer in the world disturbs me.

#5 King Mir   Members   -  Reputation: 1802

Like
0Likes
Like

Posted 03 February 2013 - 12:31 PM

To use move semantics you need a move assignment operator on the class being moved, not the buffer.

 

You can also use a buffer of unique_ptr, but this will mean that the class is allocated seperately on the heap, instead of as a continious block in the buffer.



#6 Ravyne   Crossbones+   -  Reputation: 5695

Like
0Likes
Like

Posted 03 February 2013 - 01:36 PM

You can also use a buffer of unique_ptr, but this will mean that the class is allocated seperately on the heap, instead of as a continious block in the buffer.

 

Just want to point out that, depending on what you're doing and what else is in your class, this could be perfectly fine. You'll still pay the indirection, but in terms of cache performance it might be better than if you were to have a buffer allocated as part of your class (it sounds like its heap allocated anyhow, but its not entirely clear without the source).

 

There are two downsides I can think of with this approach.

  1. The lesser issue: You can't share the data. If you needed to share it, then use shared_ptr -- you pay the cost of the reference count, but its per-shared-object, not per-sharing-object; that is, the cost is amortized across the classes sharing the object, rather than scaling up with them.
  2. The bigger issue: You essentially lose the ability to ever take any copy without destroying the original, including passing by value.

 

Enabling move semantics is also fine, this is exactly the situation it was intended for.


Edited by Ravyne, 03 February 2013 - 01:40 PM.


#7 King Mir   Members   -  Reputation: 1802

Like
0Likes
Like

Posted 03 February 2013 - 06:48 PM

You can still pass copies of the object, just not compies of the unique_ptr. That's a non-issue.



#8 Ravyne   Crossbones+   -  Reputation: 5695

Like
0Likes
Like

Posted 03 February 2013 - 10:22 PM

How do you propose that you can take a copy of an object that contains a unique_ptr? You have to move (as in std::move) the unique_ptr's ownership to the copy, thus the unique_ptr in the original object no longer owns what it was pointing to, or even has its address.

The original object is not destructed, but it no longer holds that reference. Its incomplete and probably worthless.

[Edit] See my follow-up below.

Edited by Ravyne, 14 February 2013 - 05:44 PM.


#9 King Mir   Members   -  Reputation: 1802

Like
0Likes
Like

Posted 04 February 2013 - 05:54 AM

I read your post to imply that you can't pass a copy of the contained object. But for the container, you can explicitly deep-copy it in a wrapper class (which you often want to have anyway). Also, you generally want to avoid coping big containers anyway.


Edited by King Mir, 14 February 2013 - 10:51 PM.


#10 Ravyne   Crossbones+   -  Reputation: 5695

Like
0Likes
Like

Posted 14 February 2013 - 05:54 PM

To follow up, you can't just copy a unique_ptr because its it doesn't support copy-construction or copy-assign -- to move the contents of one unique_ptr into another, you explicitly release the source ptr and explicitly reset the destination ptr to the source. Because this is not provided for, your own objects that contain unique_ptr objects cannot be trivially copied either.

 

To clarify the point I was trying to get across, to make your own unique_ptr-containing objects copyable you have to implement your copy constructor and copy-assignment operator to explicitly exchange ownership of those unique_ptr resources. However, doing that hides the ownership semantics from client code in a non-obvious way. A preferable solution would be for your own objects to either expose an explicit release/reset interface (like unique_ptr) themselves. There might also be ways to implement the object which neatly side-steps the transfer of ownership (such as by adding a level of indirection, or some kind of "wrapper" as King Mir might be suggesting), but I honestly have a hard time thinking of any use-cases that wouldn't simply be better off using shared_ptr in the first place.



#11 King Mir   Members   -  Reputation: 1802

Like
0Likes
Like

Posted 14 February 2013 - 11:35 PM

Why would you want the container copying to exchange ownership? Similarly, using shared pointers doesn't make sense, because changes to the copy will affect the original. For a container, copying should generally deep-copy every element.
Copy on write semantics can also be useful, as an optimization. Or just don't allow copying.

 

It's true that the default copy operatations wouldn't work if your class holds unique pointers, but you can still write copy operations that do the right thing yourself. Alternatively, you could write your own smart pointer that has the right copy semantics, and an efficient move. I suspect in this case the way to go is to just modify the contained object to have move semantics.






Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS