C ++ std:.auto_ptr或std :: unique_ptr(支持多个编译器,甚至是旧的C ++ 03编译器)?

时间:2016-11-30 16:40:03

标签: c++ c++11 smart-pointers c++03

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

我知道在C ++ 11编译器中不推荐使用std :: auto_ptr,但由于编译器支持较旧,我不能只用std :: unique_ptr替换它们。

有没有一个很好的做法来处理这个“旧的编译器支持,但是开始转向C ++ 11”?

3 个答案:

答案 0 :(得分:5)

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

转到c ++ 11 std :: unique_ptr<>正如Herb Sutter所说的那样,这是正确的方法 GotW89

  
      
  1. 与auto_ptr有什么关系?
      auto_ptr最为慈善的特征是在C ++移动语义之前创建unique_ptr的勇敢尝试。 auto_ptr现已弃用,不应在新代码中使用   如果您在现有代码库中有auto_ptr,那么当您有机会尝试将auto_ptr全局搜索并替换为unique_ptr时;绝大多数用法都是一样的,它可能会暴露(作为编译时错误)或修复(默默地)你不知道的一两个错误。
  2.   

请注意,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'(只是有条件地更改了typedef),可能看起来不那么尴尬了。

选项3

有条件地使用using和aliasing来“定义”auto_ptr(并在没有std :: namespace的情况下引用它)。

  

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

缺点:你继续使用“auto_ptr”,但在c ++ 11中它意味着std :: unique_ptr。
真的很困惑......

选项3.1

可能略好于选项2:
使用别名反转并更喜欢unique_ptr名称。

选项4

将std :: smart指针(有条件地为auto_ptr或unique_ptr)包装在您自己定义的模板智能指针类中。
这可能很麻烦,需要使用新类搜索和替换所有auto_ptr引用。

其他脏选项

其他选项涉及std :: namespace中的定义,我认为这是标准所禁止的 或者使用预处理器#define来... ehm ...将old_ptr“重命名”为auto_ptr,仅用于旧的C ++ 03编译器。

答案 1 :(得分:3)

在这种情况下,您可以使用boost::unique_ptr代替auto_ptr来开始使代码现代化,这是不推荐的。

总体而言,C ++ 11库的很大一部分是直接从boost中获取的,因此它将是一个很好的起点。

答案 2 :(得分:1)

如果我是认真的,我会创建一个notstd命名空间。

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

C ++ 03 notstd代码与C ++ 11 std不是100%兼容,而是有效的C ++ 03 notstd反过来会产生有效的C + +11行为。

例如,我可能会使用特殊标记的"参考包装"喜欢notstd::move引用的类型而不是右值引用,并且我的仅移动类型需要这样的标记"引用包装" 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>。没有隐含的右值转换,因此您移动notstd::unique_ptr<T>的每个位置都必须notstd::move

可悲的是,这意味着notstd::unique_ptr<T>无法放入std个容器中。可能需要做一些黑客才能使其工作(auto_ptr也不能安全地工作。

这是一项非常重要的任务。 boost::unique_ptr试图在C ++ 03中生成类似于语义的unique_ptr,并且它们将比你最有可能做得更好。如果您不能直接使用它们,请阅读它们所做的事情并自行重新实现。