如何在不复制的情况下取消引用使用New创建的指针?

时间:2016-02-18 08:39:56

标签: c++ pointers dereference

在下面的代码片段中,我通过new运算符创建一个对象并将其分配给指针。我想要做的是将它指向的对象添加到矢量。似乎正在发生的事情是我正在创建对象,然后当我取消引用它时,这会创建对原始对象的引用。因此,当我将此对Object的引用赋给向量时,它会创建一个副本,而我想要实际的对象。任何帮助都会非常感激。

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.
}

*注意:上面的代码是我想要完成的代码的一个非常简化的版本。

关于与此接口的代码的注释,此代码与OpenGL交互,因此OBJVec必须包含对象。

我已经解决了这个问题很长一段时间了,任何帮助都会很精彩。

4 个答案:

答案 0 :(得分:1)

行为正确

这是std::vector::push_back

的签名
void push_back( const T& value );
void push_back( T&& value );

当您取消引用指针时,您现在可以引用原始对象。将左值引用传递给push_back时,会选择第一个重载。

在你的第二种情况下,它也是一个左值,所以第一次重载仍然被选中......你不能躲避push_back上的复制,除非你传递rvalue或明确{{ 1}}它

如果你想要指针,那么让你的容器成为指针。 如果您想要参考,那么让您的容器为reference_wrapper到您的对象

但是,如果你做那些路线

,你有额外的内存管理工作要做

答案 1 :(得分:1)

由于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);
}

但是,一旦将元素从向量中移除并且不再使用它们,则需要释放元素。为简化此操作,您可以改为使用unique_ptr s的向量,它是智能指针,一旦不再需要就为您解除分配对象。

如果您需要指针向量,则无法应用此变通方法。然后,您不能对向量之外的每个对象使用new。这必然会导致对象被分开分配,而不是确保连续的内存布局,这是任何采用数组的OpenGL函数所要求的。您需要使用new Object[count]来分配一个数组,或者只是完全放弃手动内存的想法,只使用对象向量而不在其外部分配元素。

1)你可以改变那种行为,但是仍然不可能像你现在那样在向量之外自己分配每个元素。

答案 2 :(得分:0)

我认为这应该更好(这样你就不会复制任何东西):

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

addToVec(O); 

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

答案 3 :(得分:0)

在C ++ 98中,没有移动的概念,所以你必须使用指针向量而复制在那里引用你的原始对象。在C ++ 11中,您确实具有移动语义,以便您可以使用std::move逐字移动对象。但是,我不确定这是否是一个好主意。

首先,使用裸new这一天并不算是一种好习惯。您应该使用一些智能指针或您自己的RAII包装器。在您的情况下,我只需使用std::unique_pointer(C ++ 11 - 或boost::unique_pointer),然后只使用std::vector<std::unique_pointer<your_type>>我可以安全地移动指针(您可以&#39;复制std::unique_pointer)。这种方法没有真正的开销,所以如果你需要堆分配和独特的所有权,这可能是要走的路。

如果你不需要堆分配,并且你在c ++ 11中,那么你真的不需要首先使用指针。只需创建您的对象并随时将其移动到向量内 - 但请确保您再也不使用原始对象!