我正在尝试更新一些C ++代码,我想转向更现代的代码(c ++ 11),但我仍然需要使用一些较旧的编译器编译代码(符合c ++ 03) ,因为受支持的平台约束。
我知道在C ++ 11编译器中不推荐使用std :: auto_ptr,但由于编译器支持较旧,我不能只用std :: unique_ptr替换它们。
有没有一个很好的做法来处理这个“旧的编译器支持,但是开始转向C ++ 11”?
答案 0 :(得分:5)
如您所述,std :: auto_ptr<>已在C ++ 11中弃用 (Reference)。
转到c ++ 11 std :: unique_ptr<>正如Herb Sutter所说的那样,这是正确的方法 GotW89:
- 与auto_ptr有什么关系?
醇>
auto_ptr最为慈善的特征是在C ++移动语义之前创建unique_ptr的勇敢尝试。 auto_ptr现已弃用,不应在新代码中使用 如果您在现有代码库中有auto_ptr,那么当您有机会尝试将auto_ptr全局搜索并替换为unique_ptr时;绝大多数用法都是一样的,它可能会暴露(作为编译时错误)或修复(默默地)你不知道的一两个错误。
请注意,C ++ 17将删除std :: auto_ptr。
我认为可能有不同的方法来解决您的问题,“正确的”也取决于您的实际代码的编写方式。
一些选项是:
使用boost :: unique_ptr
有条件地使用基于__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),可能看起来不那么尴尬了。
有条件地使用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。
真的很困惑......
可能略好于选项2:
使用别名反转并更喜欢unique_ptr名称。
将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中,notstd
由std
类型的一系列别名组成。在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,并且它们将比你最有可能做得更好。如果您不能直接使用它们,请阅读它们所做的事情并自行重新实现。