混合boost :: optional和std :: unique_ptr [英] Mix boost::optional and std::unique_ptr

查看:116
本文介绍了混合boost :: optional和std :: unique_ptr的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我承认:我爱上了可选的概念。自从发现以来,我的代码质量已经有了很大的提高。与普通错误代码和带内信令相比,使变量明确或无效可能要好得多。这也使我不必担心必须阅读文档中的合同,也不必担心它是否是最新的:代码本身就是合同。

I admit it: I'm in love with the concept of optional. The quality of my code has improved so much ever since I discovered it. Making it explicit whether a variable may or may not be valid is so much better than plain error codes and in-band signaling. It also allows me to not worry about having to read the contract in the documentation, or worrying about whether it's up-to-date: the code itself is the contract.

也就是说,有时我需要处理 std :: unique_ptr 。此类型的对象可能为null;否则为null。在代码的给定点上,无法知道 std :: unique_ptr 是否应该有值;

That said, sometimes I need to deal with std::unique_ptr. Objects of this type might be null or not; at a given point in the code is impossible to know whether the std::unique_ptr is supposed to have a value or not; it's impossible to know the contract from the code.

我想以某种方式将可选(也许与 boost :: optional )和 std :: unique_ptr ,这样我就拥有了一个具有范围破坏性的动态分配对象并明确指出其可能没有值的正确复制/移动行为。这样,我可以使用这种新类型来明确指出有必要进行值检查,并避免对 std :: unique_ptr 进行不必要的检查。

I would like to somehow mix optional (maybe withboost::optional) and std::unique_ptr, so that I have a dynamically allocated object with scope-destruction and proper copy/move behaviour that explicitly states that it may not have a value. That way, I can use this new type to make it explicit that a check for value is necessary and avoid unnecessary checks for plain std::unique_ptr.

在C ++ 11标准中是否有用于此目的的工具, boost 或足够流行的库?我可以接受为此定义自己的类,但这将是最不推荐使用的方法(由于缺乏全面的测试)。

Is there a tool for this inside the C++11 standard, boost or a popular enough library? I could accept defining my own class for this, but that would be the least preferred method (due to lack of thorough testing).

推荐答案

所以要重述您的问题,您需要:

So to recap your question, you want:


  1. 按值/在堆栈上分配的非可选类型:您是

  2. 由值/在堆栈上分配的可选类型:您很高兴使用 boost :: optional 为此(或者您可以使用C ++ 17中的 std :: optional )。

  3. 非可选在堆上分配并拥有指向对象的类型。

  4. 在堆上分配并拥有指向对象的可选类型。

  1. A non-optional type that is allocated by value/on the stack: You are happy directly using the object type for this.
  2. An optional type that is allocated by value/on the stack: You are happy using boost::optional for this (or you can use std::optional from C++17).
  3. A non-optional type that is allocated on the heap and owns the pointed-to object.
  4. An optional type that is allocated on the heap and owns the pointed-to object.

您不满意可以表示1和2之间的差异,但是3和4通常都使用相同的类型( std :: unique_ptr )。您建议为3使用 std :: unique_ptr ,从不允许 nullptr 和其他用于4的东西,但要知道您可以使用什么。 (在注释中,您还接受将 std :: unique_ptr nullptr 一起使用的可能性,如果可以使用其他方法,则为4找到3)。

You are unhappy that you can express the difference between 1 and 2, but both 3 and 4 usually use the same type (std::unique_ptr). You suggest using std::unique_ptr for 3, never allowing nullptr, and some other thing for 4, but want to know what you can use. (In the comments you also accept the possibility of using std::unique_ptr with nullptr for 4 if something else can be found for 3.)

从字面上看您的问题:您可以简单地使用 boost :: optional< std: :unique_ptr< T>> (如果您建议使用裸露的 unique_ptr ,则为4)。

Literal answer to your question: you can simply use boost::optional<std::unique_ptr<T>> for 4 (while using a bare unique_ptr for 3 as you suggested).

问题的另一种字面答案:如@StoryTeller所说,您可以定义自己的智能指针类型,例如 unique_ptr ,但不允许 nullptr ,并将其用于3。一种更快(但很脏)的替代方法是强制函数返回 unique_ptr 的$ c>和对该对象的引用。然后仅通过引用访问结果,只有在 unique_ptr 仍然存在的情况下才可以访问结果:

Alternative literal answer to your question: As @StoryTeller said, you could define your own smart pointer type that is like unique_ptr but disallows nullptr, and use that for 3. A quicker (but very dirty) alternative is to force functions to return a pair of both a unique_ptr and a reference to that same object. Then only access the result through the reference, but only do so while the unique_ptr still exists:

template<class T>
using RefAndPtr = std::pair<T&, std::unique_ptr<T>>;

RefAndPtr<Foo> getFoo()
{
    std::unique_ptr<Foo> result = std::make_unique<Foo>();
    return RefAndPtr<Foo>(*result, std::move(result));
}

我的实际建议:对于3和4都使用 std :: unique_ptr 澄清类型系统中的意图是一件好事,但是过多的好事可能是不好的。使用以上两个选项中的任一个只会使任何读取您的代码的人感到困惑。而且,即使您阻止人们错误地传递 nullptr ,还是要阻止他们将指针传递给错误的对象或已经释放的内存等?在某些时候,您必须指定类型系统之外的内容。

My actual suggestion: Just suck it up and use std::unique_ptr for both 3 and 4. Clarifying your intentions in the type system is a good thing, but too much of a good thing can be bad. Using either of the above options is just going to confuse the hell out of anyone that reads your code. And even if you stop people from incorrectly passing around nullptr, what's to stop them passing a pointer around to the wrong object, or already-freed memory, etc.? At some point you have to specify things outside of the type system.

这篇关于混合boost :: optional和std :: unique_ptr的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆