C++ 如何将现有对象的地址分配给智能指针?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/28502067/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to assign the address of an existing object to a smart pointer?
提问by Tomasz Kasperczyk
#include <memory>
class bar{};
void foo(bar &object){
std::unique_ptr<bar> pointer = &object;
}
I want to assign an address of the object to the pointer. The above code obviously wont compile, because the right side of the assignment operator needs to be a std::unique_ptr. I've already tried this:
我想将对象的地址分配给指针。上面的代码显然无法编译,因为赋值运算符的右侧需要是 std::unique_ptr。我已经试过了:
pointer = std::make_unique<bar>(object)
But it throws many errors during compilation. How can I do that?
但是在编译过程中会抛出很多错误。我怎样才能做到这一点?
Update
As said in the answers - using the std::unique_ptr::reset
method led to undefined behaviour. Now I know, that in such cases I should use a standard pointer.
更新
正如答案中所说 - 使用该std::unique_ptr::reset
方法导致未定义的行为。现在我知道,在这种情况下我应该使用标准指针。
采纳答案by Raydel Miranda
void foo(bar &object){
std::unique_ptr<bar> pointer;
pointer.reset(&object);
}
But be aware this is not recommended, you should not create a unique_ptr
to a reference that is being passed to a function. At the end of the function, when pointer
is being destroyed it will try to destroy object
as well, and it won't be available outside the function call, resulting in an access memory error.
但请注意,这是不推荐的,您不应该创建unique_ptr
对正在传递给函数的引用。在函数结束时,当pointer
被销毁时,它也会尝试销毁object
,并且在函数调用之外不可用,从而导致访问内存错误。
Example:This will compile, but give a runtime error.
示例:这将编译,但会出现运行时错误。
struct bar{ int num;};
void foo(bar &object){
std::unique_ptr<bar> pointer;
pointer.reset(&object);
}
int main()
{
bar obj;
foo(obj);
obj.num; // obj is not a valid reference any more.
return 0;
}
On the other hand you might want to consider using shared_ptrthis can help you to decide: unique_ptr or shared_ptr?.
另一方面,您可能要考虑使用shared_ptr这可以帮助您决定:unique_ptr 还是 shared_ptr?.
回答by Damon
You can only assign another unique_ptr
or the nullptr
. If you think about it, this makes sense, too (though reset
will let you do what you want, but I think this is actually a bug or deficiency in unique_ptr
).
您只能分配另一个unique_ptr
或nullptr
. 如果你仔细想想,这也是有道理的(虽然reset
会让你做你想做的事,但我认为这实际上是 中的一个错误或缺陷unique_ptr
)。
A unique_ptr
is the exclusive owner of the pointed-to object. When it goes out of scope, it will delete the object.
This means that your function has sinksemantics. The pointer you pass in (or rather the pointed-to object") is consumed, that is, it "disappears" (sinks) inside the function. You pass in an object by reference (an object which is not even necessarily heap-allocated, prepare for a surprise if you pass in an object with automatic storage!) and suddenly it's gone. Bang.
Aunique_ptr
是指向对象的唯一所有者。当它超出范围时,它将删除该对象。
这意味着您的函数具有接收器语义。您传入的指针(或者更确切地说是指向的对象)被消耗,也就是说,它在函数内部“消失”(下沉)。您通过引用传入一个对象(一个甚至不一定是堆分配的对象) ,如果您传入具有自动存储功能的对象,请准备好惊喜!)然后它突然消失了。砰。
Sink semantics should be communicated properly. You should pass a unique_ptr
as function parameter. Unique pointers cannot be copied, so this will force the user of that function to use std::move
, creating awarenessof what is acutally happening.
应该正确传达接收器语义。您应该传递一个unique_ptr
as 函数参数。唯一指针无法复制,因此这将迫使该函数的用户使用std::move
,从而意识到正在发生的事情。
Having an object "disappear" is a nasty surprise, this shouldn't just happen unintentionally.
一个对象“消失”是一个令人讨厌的惊喜,这不应该只是无意中发生的。
回答by Daniel Frey
You could call std::unique_ptr::reset
:
你可以打电话std::unique_ptr::reset
:
pointer.reset(&object);
but the real question is: Is this really doing what you expect it to do?If the object was not created via new
, the above can be quite dangerous. Given that you haven't provided more information, you mighthave a valid use-case - but without this information it seems like a possible source of future trouble. What you effectively do in your example is that you consumethe object, i.e., after the function has been called the lifetime of the unique_ptr
ended and the object has been deleted. If this is documented/clear to the caller, it might be OK - otherwise rethink the design. And even if this is intended design, it is much better to use a unique_ptr
as the argument of the function itself:
但真正的问题是:这真的按照你的期望去做吗?如果对象不是通过创建的new
,则上述内容可能非常危险。鉴于您没有提供更多信息,您可能有一个有效的用例 - 但如果没有这些信息,它似乎是未来麻烦的可能来源。你在你的例子中有效地做的是你消费对象,即在函数被调用之后unique_ptr
结束的生命周期并且对象已被删除。如果这对调用者记录/清楚,则可能没问题 - 否则重新考虑设计。即使这是预期的设计,最好使用 aunique_ptr
作为函数本身的参数:
void foo(std::unique_ptr<bar> pointer)
{
// ...
}
This does two things:
这有两件事:
- It communicates to the caller that the function will take ownership of the passed object.
- It prevents resource leaks.
- 它向调用者传达该函数将获得所传递对象的所有权。
- 它可以防止资源泄漏。
回答by Dorin Laz?r
Allow me to disappoint you, but you don't. You have there a reference, which can point to either a dynamically allocated object or a stack allocated object, or, maybe, an object in a dynamically allocated array, which was not individually allocated.
让我让你失望,但你没有。你有一个引用,它可以指向一个动态分配的对象或一个堆栈分配的对象,或者,一个动态分配的数组中的对象,它不是单独分配的。
You want to place its address in a class that will automatically call delete on that address. Which is invalid for most situations presented above. That is wrong. So passing a reference and putting the address of the reference in a smart pointer should never be done, ever. Especially not with reset().
您想将其地址放在一个类中,该类将自动对该地址调用 delete。对于上面介绍的大多数情况,这是无效的。那是错的。因此,永远不应传递引用并将引用的地址放入智能指针中。尤其是不使用reset()。
At most, what you may want to do is initialize the smart pointer with the newly allocated object, for example:
最多,您可能想要做的是使用新分配的对象初始化智能指针,例如:
auto ptr = std::unique_ptr<X>(new X(p1, p2));
Do not ever take the address of a reference. Ever. For no reason. It's morally wrong. It's not because the use of reference addresses is invalid, because it can be valid use; it's because two months later the new colleague will want to use that address with a smart pointer because that's how (s)he heard it's done nowadays, and then come to Stack Overflow and read that they should use ?reset” for that pointer. Which is wrong, painfully wrong.
永远不要取参考的地址。曾经。没原因。这在道德上是错误的。不是因为引用地址的使用无效,而是可以有效使用;这是因为两个月后,新同事将要使用带有智能指针的地址,因为这就是他听说现在已经完成的方式,然后来到 Stack Overflow 并阅读他们应该使用 ?reset” 作为该指针。这是错误的,痛苦的错误。
回答by Milan
What I can see is, you want to have unique_ptr object, which points to some object in memory,but you don't want to transfer the ownership of the memory.
我能看到的是,你想要一个 unique_ptr 对象,它指向内存中的某个对象,但你不想转移内存的所有权。
You need to create custom deleter for the object, which actually does not delete the object:
您需要为对象创建自定义删除器,它实际上不会删除对象:
class bar{};
struct barfakedeleter
{
void operator()(bar*){/* do nothing here*/}
};
unique_ptr is a template where the second argument is the deleter of the object. By default it is default_deleter, but you can exchange it with this fake one:
unique_ptr 是一个模板,其中第二个参数是对象的删除器。默认情况下它是 default_deleter,但你可以用这个假的来交换它:
void foo(bar& object)
{
unique_ptr<bar,barfakedeleter> pointer(&object);
....
}
post edit: Same you can do with shared_ptr, but because shared_ptr can be cast to other shared_ptr within inheritance tree of the object, the deleter is not stored in class template argument, but it is past as instance member. This actually makes it easier to use IMO:
后编辑:你可以用shared_ptr做同样的事情,但是因为shared_ptr可以转换为对象继承树中的其他shared_ptr,删除器不存储在类模板参数中,但它作为实例成员过去。这实际上使使用 IMO 变得更容易:
void foo(bar& object)
{
shared_ptr<bar> pointer(&object,[](bar*){}); // just use anonymous function, which will not delete the object
}
You can do some custom release of resources as well:
您也可以执行一些自定义资源释放:
shared_ptr<ObjectClass> pointer(GetObject(),[](ObjectClass* obj){ ReleaseTheObject(obj);});
回答by emlai
The function you're looking for is reset()
. Here's an example:
您正在寻找的功能是reset()
. 下面是一个例子:
pointer.reset(&object);
Here pointer
is a unique_ptr
. Calling reset()
will destroy the previous object managed by pointer
(if there was any), and make object
the current managed object of pointer
.
这pointer
是一个unique_ptr
. 调用reset()
将销毁之前管理的对象pointer
(如果有的话),并使object
当前管理的对象为pointer
。
Or, if you want to make object
the managed object right when you initialize the unique_ptr
:
或者,如果您想object
在初始化时使托管对象正确unique_ptr
:
std::unique_ptr<bar> pointer(&object);
A word of warning though:object
should be allocated with new
if you're going to manage it by a unique_ptr
, because unique_ptr
may try to call delete
on it. If it was not created with new
don't wrap it in a unique_ptr
, that's not what they're for.
不过有一句警告:如果您要通过 a 管理它object
,new
则应该分配给它unique_ptr
,因为unique_ptr
可能会尝试调用delete
它。如果它不是创建的,new
不要将它包装在 a 中unique_ptr
,那不是它们的用途。