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

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

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

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 必须包含对象。

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

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

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

addToVec(O); 

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

行为是对的

这是std::vector::push_back

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

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

在你的第二种情况下,它也是一个左值,所以第一个重载仍然被选择......你不能在 push_back 上躲避复制,除非你传递 rvalue 或显式 std::move

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

但是,如果您执行这些路线,您需要进行额外的内存管理工作

因为 std::vector 处理它自己的内存分配(默认情况下)1,你不能在它之外分配一个元素然后让 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 的矢量,即 智能指针 ,一旦不再需要,它会为您解除分配对象。

如果您需要指针向量,则不能应用此解决方法。那么你不能对向量外的每个对象使用 new 。这必然导致对象被单独分配,不能确保连续的内存布局,正如任何采用数组的 OpenGL 函数所要求的那样。您需要使用 new Object[count] 分配一个数组,或者干脆完全放弃手动内存的想法,只使用一个对象向量而不分配它之外的元素。


1) 您可以更改该行为,但仍然不可能像您目前所做的那样在向量之外单独分配每个元素。

在 C++98 中没有 moving 的概念,因此您将不得不使用指针向量来代替 copy有对您原始对象的引用。在 C++11 中,您确实具有移动语义,因此您可以使用 std::move 字面上移动对象。但是,我不确定这对您来说是否是个好主意。

首先,现在使用裸 new 不被认为是一种好的做法。您应该使用一些智能指针或您自己的 RAII 包装器。在你的情况下,我会简单地使用 std::unique_pointer (C++11 - 或 boost::unique_pointer)然后简单地使用 std::vector<std::unique_pointer<your_type>> 我可以安全地移动指针(你不能复制 std::unique_pointer).这种方法没有真正的开销,所以如果您需要堆分配和唯一所有权,这可能是可行的方法。

如果您不需要堆分配并且您使用的是 c++11,那么您实际上一开始就不需要使用指针。只需创建您的对象并在需要时将其移动到向量中 - 但是,请确保您不再使用原始对象!