简体   繁体   中英

How can I dereference a pointer created with New without copying?

In the code snippet below I am creating an object via the new operator and assigning it to a pointer. What I would like to do is add the object that it points to to a vector. What seems to be happening is I am creating the object fine, then when I de-reference it, this creates a reference to the original object. So when I assign this reference to Object to the vector it creates a copy, whereas I would like the actual object. Any help would be really appreciated.

std::vector<Object> OBJVec;

Object *O = new Object();
/*Edits some of the internals*/
addToVec(*O); //Here is the beginning of the problem: this passes a reference to the content of O.

void addToVec(Object OParam){ //Here Creates a copy of O instead of passing the actual content.
    OBJVec.push_back(OParam); // Pushes a copy of content instead of content.
}

*Note:The Above Code is a very simplified version of the code I am trying to accomplish.

A note about the Code this interfaces with, This code is interacting with OpenGL and therefore OBJVec must contain Objects.

I have worked on this problem for quite some time, any help would be wonderful.

The behavior is right

This is the signature of std::vector::push_back

void push_back( const T& value );
void push_back( T&& value );

when you dereference your pointer, you now have a reference to the original object. When you pass an lvalue reference to push_back the first overload is picked.

In your second case, its also an lvalue, so the first overload is still picked... You can't dodge copying on push_back except you pass an rvalue or explicitly std::move it

If you want pointers, then let your container be that of pointers. If you want reference, then let your container be of reference_wrapper to your object

But, you have extra memory management work to do if you do those route

Since std::vector handles its own memory allocation (as per default) 1 , you can't allocate an element outside of it and then make vector point to it, unless you make the vector's value_type a pointer by itself, that is std::vector<Object*> , and pass the pointer itself to addToVec .

std::vector<Object*> OBJVec; // Make a vector of pointers instead of objects
Object *O = new Object();

addToVec(O); // Do not dereference here

void addToVec(Object *OParam) { // Use a pointer here as the argument
    OBJVec.push_back(OParam);
}

However, then you would need to deallocate the elements once you remove them out of the vector and are not using them anymore. To simplify this, you could instead use a vector of unique_ptr s, that are smart pointers which deallocate the object for you once not needed anymore.

If you need a vector of pointers, you can't apply this workaround. Then you can't use new for every single object outside of the vector. This would necessarily lead to the objects being allocated separatedly, not ensuring contiguous memory layout, as required by any OpenGL function taking an array. You would need to allocate an array with new Object[count] instead, or simply drop the idea of manual memory altogether and just use a vector of objects without allocating the elements outside of it.


1) You could change that behavior, but it would still be impossible to allocate every element by itself outside of the vector, like you currently do.

I think this should be better (this way you are not copying anything):

std::vector<Object*> OBJVec;
Object *O = new Object();

addToVec(O); 

void addToVec(Object* OParam){
    OBJVec.push_back(OParam);
}

In C++98 there is no notion for moving so you will have to use a vector of pointers instead and copy in there a reference to you original object. In C++11 you do have move semantics so that you can literally move an object using std::move . I'm not sure if this is a good idea in your case, however.

In the first place using naked new is not considered a good practice these days. You should use some smart pointer or your own RAII wrapper. In your case I'd simply use std::unique_pointer (C++11 - or boost::unique_pointer ) and then simply a std::vector<std::unique_pointer<your_type>> where I could safely move the pointer (you can't copy a std::unique_pointer ). There is no real overhead in this approach so if you need heap allocation and unique ownership this is probably the way to go.

If you don't need heap allocation and you're in c++11, then you don't really need to use pointers in the first place. Just create your object and move it inside the vector whenever you want - make sure, however, that you never use the original object again!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM