C std:.auto_ptr或std :: suolide_ptr(支持多个编译器,甚至旧的C 03编译器

C++ std:.auto_ptr or std::unique_ptr (to support multiple compilers, even old C++03 compilers)?

本文关键字:编译器 ptr std 支持 auto suolide      更新时间:2023-10-16

我正在尝试更新一些C 代码,我想转向更现代的代码(C 11),但是我仍然需要使用一些较旧的代码来编译代码编译器(C 03符合),由于受支持的平台约束。

我知道在C 11编译器std :: auto_ptr已弃用,但是由于较旧的编译器支持,我不能只是用std :: simolor_ptr。

替换它们

是否有一个很好的做法来处理此"旧编译器支持,但开始转到C 11"?

如您所述,std :: auto_ptr<>在C 11中已弃用(参考)。

移至C 11 std :: suolide_ptr<>是正确的方式,正如Herb Sutter所指出的gotw89:

  1. 与auto_ptr有什么关系?
    Auto_ptr最慈善地描述为在C 具有移动语义之前创建唯一_ptr的英勇尝试。Auto_ptr现在已弃用,不应在新代码中使用。
    如果您在现有代码库中具有auto_ptr,则有机会尝试将auto_ptr的全局搜索和重新安置到unique_ptr;绝大多数用途都可以正常工作,它可能会暴露(作为编译时间错误)或(默默地修复)一个或两个您不知道的错误。

还请注意,C 17将删除std :: auto_ptr。

我认为解决您的问题可能有不同的方法,"正确"一个也取决于您的实际代码的编写。
一些选择是:

选项1

使用boost :: unique_ptr

选项2

有条件地使用基于__cplusplus的auto_ptr或unique_ptr。

类myclass {
#if __cplusplus<201103L
std :: auto_ptr m_ptr;
#else
std :: unique_ptr m_ptr;
#endif
...

这将散布在您引用auto_ptr的每个地方,我真的不喜欢它。
如果您对std :: auto_ptr的所有引用已经键入(只要有条件地更改typedef)。

选项3

有条件地使用并将其混音到"定义"auto_ptr(并在没有std ::名称空间的情况下引用它)。

#if __cplusplus<201103L
使用std :: auto_ptr;
#else
模板
使用auto_ptr = std :: unique_ptr;
#endif

缺点:您一直使用" auto_ptr",但是在C 11中,这意味着std :: simelor_ptr。
真的很困惑...

选项3.1

可能比选项2好一点:
反向使用别名,更喜欢unique_ptr名称。

选项4

将STD ::智能指针(有条件地auto_ptr或unique_ptr)在您自己定义的模板中智能指针类。
这可能很麻烦,需要在您的新课程中搜索和更换所有auto_ptr。

其他肮脏的选项

其他选项涉及std ::名称空间内的定义,我认为标准禁止,
或使用预处理器#Define进行... ehm ...unique_ptr到auto_ptr仅适用于旧的C 03编译器。

在这种确切情况下,您可以使用boost::unique_ptr而不是auto_ptr开始对代码进行现代化,不推荐。

总的来说,C 11库的大部分是直接从Boost拿来的,因此它将是开始的好地方。

如果我很认真,我会创建一个notstd名称空间。

目标是在C 11中,notstdstd类型的一系列别名组成。在C 03中,它具有伪C 11代码。

C 03 notstd代码与C 11 std不兼容,而是有效的C 03 notstd又会产生有效的C 11行为。

例如,我可能会使用特殊标记的"参考 - wrapper"类型用于notstd::move参考而不是RVALUE参考,并且让我的仅移动类型需要此类标记的"参考 - wrapper"s。

namespace notstd {
  template<class U>
  struct moved_t {
    U& u;
    // relies on NRVO, which is pretty universally supported.
    // also relies in U being default-constructible:
    operator U()const{ U tmp; std::swap(u, tmp); return tmp; }
  };
  template<class U>
  moved_t<U> move(U& u) { return {u}; }
  template<class T>
  struct unique_ptr {
    unique_ptr( moved_t<unique_ptr<T>> > ); // move ctor
    template<class U>
    unique_ptr( moved_t<unique_ptr<U>> > ); // move ctor
  private:
    unique_ptr(unique_ptr const&);
  };
}

,您的代码将使用notstd::unique_ptr<T>。不会有隐式的rvalue转换,因此每个移动notstd::unique_ptr<T>的位置都必须notstd::move

可悲的是,这意味着notstd::unique_ptr<T>不能放入std容器中。可能必须进行一些黑客攻击才能使其工作(auto_ptr也不能安全)。

这是一项非平凡的任务。boost::unique_ptr试图在C 03中生成唯一的_ptr,他们将做得比您最有可能的工作更好。如果您不能直接使用它们,请阅读他们所做的工作,然后自己重新实现。