简体   繁体   English

如何取消引用用New创建的指针而不进行复制?

[英]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. 在下面的代码片段中,我通过new运算符创建了一个对象,并将其分配给指针。 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. 因此,当我将此对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. 关于此代码与之交互的代码的注释,该代码与OpenGL交互,因此OBJVec必须包含对象。

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 这是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. 将左值引用传递给push_back将选择第一个重载。

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 在第二种情况下,它也是一个左值,因此仍然会选择第一个重载...您不能在push_back上闪避复制,除非您传递了一个rvalue或显式的std::move

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 如果要引用,则让您的容器成为对象的reference_wrapper

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处理其自己的内存分配(默认情况下) 1 ,因此您无法在其外部分配元素,然后使vector指向该元素,除非您单独使vector的value_type成为指针,即std::vector<Object*> ,并将指针本身传递给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. 为了简化此操作,您可以改用unique_ptr的向量,它们是智能指针 ,可以一次不再需要时为您取消分配对象。

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. 然后,您不能对vector之外的每个单个对象使用new This would necessarily lead to the objects being allocated separatedly, not ensuring contiguous memory layout, as required by any OpenGL function taking an array. 这必然导致对象被分开分配,而不是确保任何采用数组的OpenGL函数所要求的连续内存布局。 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. 您可能需要分配一个带有new Object[count]的数组,或者干脆完全放弃手动存储的想法,只使用对象向量而不在其外部分配元素。


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. 1)您可以更改该行为,但是像现在这样,仍然不可能在向量之外自行分配每个元素。

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. 在C ++ 98中,没有移动的概念,因此您将不得不使用指针向量代替,然后在其中复制对原始对象的引用。 In C++11 you do have move semantics so that you can literally move an object using std::move . 在C ++ 11中,您确实具有移动语义,因此您可以使用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. 首先,这些天不使用裸露的new You should use some smart pointer or your own RAII wrapper. 您应该使用一些智能指针或您自己的RAII包装器。 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 ). 在您的情况下,我只使用std::unique_pointer (C ++ 11-或boost::unique_pointer ),然后简单地使用std::vector<std::unique_pointer<your_type>>即可安全地移动指针(您可以无法复制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. 如果您不需要堆分配并且您使用的是c ++ 11,那么您实际上不需要首先使用指针。 Just create your object and move it inside the vector whenever you want - make sure, however, that you never use the original object again! 只需创建您的对象并将其移动到矢量中即可,但是请确保不要再使用原始对象!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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