简体   繁体   English

在这种情况下我应该使用智能指针吗?

[英]Should I use smart pointers in this situation?

I know that the go-to rule is to always use shared_ptr s or other smart pointers. 我知道转到规则是始终使用shared_ptr或其他智能指针。 However, I'm not sure how exactly to implement it without copy ctor'ing with std::make_shared . 但是,我不确定在不使用std::make_shared复制代码的情况下如何准确地实现它。 I'll elaborate: 我会详细说明:

The problem 问题

I want to create a tree-like expression, like: 我想创建一个类似树的表达式,例如:

struct foo{
    std::vector<foo*> v;
};

This allows me to do the following: 这使我可以执行以下操作:

foo add(foo& f1, foo& f2){
    return foo {&f1, &f2};
}

That's good, because then the two will become children of a new node. 那样很好,因为这两个将成为新节点的子代。

I want the following to be evaluated correctly: 我希望对以下内容进行正确评估:

foo x, y;
auto z = add(x,y);
assert(z.v[0] == &x && z.v[1] == &y);

This way, there's no copying and it's all good. 这样,就没有复制,而且一切都很好。 However, we have a resource management issue here. 但是,这里有一个资源管理问题。

Addressing the resource management issue 解决资源管理问题

If these elements are allocated on the heap, and someone unknowingly might, then we'll run into a memory leak. 如果这些元素分配在堆上,并且可能在不知不觉中有人在分配,那么我们将遇到内存泄漏。 So the best way to do this is to use smart pointers for RAII: 因此,做到这一点的最佳方法是为RAII使用智能指针:

struct foo{
    std::vector<std::shared_ptr<foo> > v;
};

foo add(foo& f1, foo& f2){
    return foo {std::make_shared<foo>(f1), std::make_shared<foo>(f2)};
}

This is good, but we're calling the copy ctor of f1 and f2 here . 很好,但是我们在这里调用f1和f2的副本ctor Suppose copying takes a long time and we don't want to incur that cost. 假设复制需要很长时间,并且我们不想承担该费用。

We definitely, cannot do: 我们绝对不能:

foo add(foo& f1, foo& f2){
    return foo {std::shared_ptr<foo>(&f1), std::shared_ptr<foo>(&f2)};
}

because whenever we remove z in z = x+y , we will call delete on each of x and y , which could be allocated on the stack. 因为每当我们删除z z = x+y中的z = x+y ,我们都会在xy每一个上调用delete ,它们可以分配在堆栈上。 And we definitely do not want to delete things on the stack. 而且我们绝对不想delete堆栈中的内容。

So what should I do in this case? 那么在这种情况下我该怎么办?

Let me know if I should supply more information on the context. 让我知道是否应提供有关上下文的更多信息。

Accept by smart pointer . 通过智能指针接受 Applying the notion of smart pointers correctly means you have to think about the ownership semantics of your data, and not about calling new/delete automatically. 正确应用智能指针的概念意味着您必须考虑数据的所有权语义,而不是自动调用new / delete。

You accept a reference to a non-const object. 您接受对非常量对象的引用。 This does not imply sharing, only modification of the objects. 这并不意味着共享,仅意味着对象的修改。 And as you correctly noted, just creating smart pointers to them spells disaster. 正如您正确指出的那样,仅创建指向它们的智能指针就意味着灾难。

The caller of add (even if it's just you) must know the data they pass is about to be shared. add的调用者(即使只有您自己)也必须知道他们传递的数据即将被共享。 And the only way for them to know is if they pass the smart pointer themselves. 他们知道的唯一方法是他们是否自己传递了智能指针。 So you should change add into this: 因此,您应该add更改为:

foo add(std::shared_ptr<foo> f1, std::shared_ptr<foo> f2){
    return foo{f1, f2};
}

Now, the only way a user of add can blow this up is intentionally. 现在, add用户唯一可以炸毁它的方法是故意的。 But they most likely won't. 但是他们很可能不会。 Furthermore, now said user has much more flexibility in calling your code. 此外,现在所说的用户在调用您的代码时具有更大的灵活性。 They can control the allocator and deleter for each object they pass. 他们可以控制所传递的每个对象的分配器和删除器。

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

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