Pointers C++;11当有一个所有者(std::uniqueptr)但其他对象需要一个";“处理”;到目标了吗?

Pointers C++;11当有一个所有者(std::uniqueptr)但其他对象需要一个";“处理”;到目标了吗?,pointers,c++11,Pointers,C++11,在以下情况下,我似乎发现了很多代码: class Thing { public: Thing() = default; }; class Repo { public: Repo() { // Makes things.. mThings.emplace_back( std::make_unique<Thing>() ); } // I find I need functions like this, // a function w

在以下情况下,我似乎发现了很多代码:

class Thing
{
public:
   Thing() = default;
};

class Repo
{
public:
  Repo()
  {
     // Makes things..
     mThings.emplace_back( std::make_unique<Thing>() );
  } 

  // I find I need functions like this, 
  // a function which may return some record, 
  // or might return nullptr if there is no record.
  Thing* GetThing(int id)
  {
     // Might return nullptr, or might return
     return mThings[0].get();
  }

private:
  std::vector<std::unique_ptr<Thing>> mThings;
};

是的,纯指针就足够了。但是具有指向
对象的句柄(指针)的对象必须假定所指向的对象将比它们更长寿。

有a和a,它们的作用与您需要的类似:

// make sure to include <boost/optional/optional.hpp>

boost::optional<Thing&> GetThing(int id)
{
    // Might return nullptr, or might return
    return boost::optional<Thing&>(*mThings[0]);
}
(可以直接使用
指针之类的东西;我没有测试过,我是从文档中构建的)

注意:我不完全确定即将发布的
std::optional
是否支持引用。他们。不过,这里使用引用有点重要,因为正如OP在对问题的评论中所指出的,在这里使用裸类型将导致复制,而使用原始指针作为T将有点违背目的

@JohannesD评论了一个指向的链接,该链接正是为此目的制作的。不过,我没有关于该草案状态的信息


然而:现在,我仍然倾向于在这种情况下使用原始指针,主要是因为
std::optional
还没有实现(甚至没有完全指定,可能根本不支持引用)。我也有点失望,因为它已经从C++14中删除了


确保在该函数的文档中明确说明接收方不拥有所有权。

在我看来,只要您不想将代码与多线程一起使用,这是可以接受的/OK。如果您将来可能想添加多线程,这将是一个真正的问题,因为调用方无法知道返回指针的有效时间,因为另一个线程可能会执行使指针无效的操作。在这种情况下,
std::shared\u ptr
更有意义(无论是在数据结构中还是作为返回值)。

optional
将是一个选项(双关语),但这尚未影响STL实现。在这些情况下,我返回原始指针。但是我没有任何权威的来源来回答这个问题……你能发布一个答案来解释这个东西是什么,以及如何在我的例子中使用它吗?我刚才查看了boost文档,但不确定它是否适合?它不会导致复制对象等吗?
可选
似乎合适,但允许api用户使用生命周期语义可能有点奇怪。
std::shared_ptr
。很抱歉,这与多线程无关。一个对象比另一个对象先被删除的原因有很多<代码>标准::共享_ptr
不适用于高性能代码。当所有权真正共享时,应该很少使用它。不是作为数据竞争的解决方案。@JonasWielicki:以什么方式?规范保证(该页面建议但并未真正涵盖)如果一个对象的最后两个共享\u ptr被两个不同的线程破坏,那么正好有一个线程会看到refcnt下降到0并破坏该对象。如果多个执行线程在不同步的情况下访问同一共享\u ptr引用的对象,除非使用原子函数的共享ptr重载,否则可能会发生数据竞争。再次阅读,这实际上可能指同一线程访问的单个共享
std::shared_ptr
对象。在这种情况下,它可能不会影响API,假设在传递它时复制了一个副本。@JonasWielicki,CPPPreference页面的措辞非常糟糕。
shared\u ptr
的原子操作不会阻止“被[…]
shared\u ptr
引用的对象”上的数据争用,只会在
shared\u ptr
本身上争用。我认为这是在试图说,当多个线程不同步地访问同一个
共享的\u ptr
并且至少有一个线程使用一个非常量成员函数时,就会出现数据竞争,但这很难说。它似乎试图在一句话中谈论两件不同的事情。另一个被提议的替代方案是@JohannesD,听起来它是为这种情况而设计的。你对这篇论文的现状有什么看法吗?没有,除了它已经经过了三次修订之外,至少它看起来还很有活力:)在:“对于引用类型,或者对于可能的cv限定类型,需要实例化模板
可选
就地
空选
的程序是格式错误的。“如果我回忆起关于标准提案邮件列表的讨论,我认为对于
optional
的确切语义应该是什么缺乏共识。我从cppreference.com网站上怀疑这样的事情,但是boost::optional支持它。我将修改我的答案a,使之更清楚。
// make sure to include <boost/optional/optional.hpp>

boost::optional<Thing&> GetThing(int id)
{
    // Might return nullptr, or might return
    return boost::optional<Thing&>(*mThings[0]);
}
Repo someRepo;
boost::optional<Thing&> someThing = someRepo;
if (someThing) {
    // use someThing just like a pointer
} else {
    // do not touch the value
}