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

问题描述 投票:0回答:3

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

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

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

c++ c++11 smart-pointers c++03
3个回答
6
投票

正如您所指出的,std::auto_ptr<> 在 C++11 中已被弃用 (参考)。

转向 c++11 std::unique_ptr<> 是正确的方法,正如 Herb Sutter 在 得到W89

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

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

我认为解决您的问题可能有不同的方法,“正确”的方法还取决于您的实际代码是如何编写的。
几个选项是:

选项1

使用 boost::unique_ptr

选项2

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

我的班级{
#if __cplusplus < 201103L
std::auto_ptr m_ptr;
#其他
std::unique_ptr m_ptr;
#结束
...

这会分散在你引用auto_ptr的每个地方,我不太喜欢它。
如果您对 std::auto_ptr 的所有引用都已经进行了类型定义(只需有条件地更改类型定义),可能看起来就不那么尴尬了。

选项3

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

#if __cplusplus < 201103L
使用 std::auto_ptr;
#其他
模板
使用 auto_ptr = std::unique_ptr;
#结束

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

选项3.1

可能比选项 3 稍好:
相反使用别名并更喜欢 unique_ptr 名称。

选项 4

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

其他肮脏的选择

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


3
投票

在这种情况下,您可以使用

boost::unique_ptr
而不是
auto_ptr
来开始现代化代码,但不建议这样做。

总的来说,C++11 库的很大一部分是直接取自 boost,所以这将是一个很好的起点。


2
投票

如果我是认真的,我会创建一个

notstd
命名空间。

目标是在 C++11 中,

notstd
由一系列
std
类型的别名组成。在C++03中,它有伪C++11代码。

C++03

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

例如,我可能会使用特殊标记的“引用包装器”(例如

notstd::move
引用类型)而不是右值引用,并且我的仅移动类型需要此类标记的“引用包装器”。

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 的语义的尝试,并且它们很可能会比您做得更好。如果您无法直接使用它们,请阅读它们的用途并自己重新实现。

© www.soinside.com 2019 - 2024. All rights reserved.