lau*_*ent 156 c++ api pointers smart-pointers
我在一些文章中读到,几乎从不使用原始指针.相反,它们应始终包含在智能指针内,无论是作用域还是共享指针.
但是,我注意到像Qt,wxWidgets和像Boost这样的库这样的框架永远不会返回也不会期望智能指针,就好像它们根本就没有使用它们一样.相反,他们返回或期望原始指针.有什么理由吗?当我编写公共API时,我应该远离智能指针,为什么?
只是想知道为什么许多重大项目似乎避免使用智能指针.
Jon*_*rdy 123
除了许多库是在标准智能指针出现之前编写的,最大的原因可能是缺少标准的C++应用程序二进制接口(ABI).
如果您正在编写仅限标题的库,则可以将智能指针和标准容器传递给您的内容.它们的源代码在编译时可供您的库使用,因此您只依赖于其接口的稳定性,而不是它们的实现.
但由于缺乏标准的ABI,您通常无法跨模块边界安全地传递这些对象.GCC shared_ptr
可能与MSVC不同shared_ptr
,后者也可能与英特尔不同shared_ptr
.即使使用相同的编译器,也不保证这些类在版本之间是二进制兼容的.
最重要的是,如果要分发库的预构建版本,则需要依赖标准ABI.C没有,但编译器供应商非常擅长给定平台的C库之间的互操作性 - 事实上的标准.
这种情况对C++来说并不好.各个编译器可以处理它们自己的二进制文件之间的互操作,因此您可以选择为每个受支持的编译器(通常是GCC和MSVC)分发版本.但鉴于此,大多数库只是导出一个C接口 - 这意味着原始指针.
但是,非库代码通常更喜欢智能指针而不是原始代码.
iam*_*ind 40
可能有很多原因.列出其中几个:
编辑:使用智能指针是完全开发人员的选择.这取决于各种因素.
在性能关键系统中,您可能不希望使用会产生开销的智能指针
需要向后兼容的项目,您可能不想使用具有C++ 11特定功能的智能指针
Edit2由于下面的段落,在24小时的范围内有一串几个downvotes.我不明白为什么答案被低估了,尽管下面只是一个附加建议而不是答案.
但是,C++总是方便您打开选项.:)例如
template<typename T>
struct Pointer {
#ifdef <Cpp11>
typedef std::unique_ptr<T> type;
#else
typedef T* type;
#endif
};
Run Code Online (Sandbox Code Playgroud)
在您的代码中使用它作为:
Pointer<int>::type p;
Run Code Online (Sandbox Code Playgroud)
对于那些说智能指针和原始指针不同的人,我同意这一点.上面的代码只是一个想法,人们可以编写一个可以与a互换的代码#define
,这不是强制性的 ;
例如,T*
必须显式删除,但智能指针不能删除.我们可以有一个模板Destroy()
来处理它.
template<typename T>
void Destroy (T* p)
{
delete p;
}
template<typename T>
void Destroy (std::unique_ptr<T> p)
{
// do nothing
}
Run Code Online (Sandbox Code Playgroud)
并将其用作:
Destroy(p);
Run Code Online (Sandbox Code Playgroud)
同样,对于原始指针,我们可以直接复制它,对于智能指针,我们可以使用特殊操作.
Pointer<X>::type p = new X;
Pointer<X>::type p2(Assign(p));
Run Code Online (Sandbox Code Playgroud)
哪里Assign()
是:
template<typename T>
T* Assign (T *p)
{
return p;
}
template<typename T>
... Assign (SmartPointer<T> &p)
{
// use move sematics or whateve appropriate
}
Run Code Online (Sandbox Code Playgroud)
Mat*_* M. 35
智能指针有两个问题(前C++ 11):
在默认的智能指针,因为它是无成本,是unique_ptr
.不幸的是,它需要C++ 11移动语义,它只出现在最近.所有其他智能指针都有成本(shared_ptr
,intrusive_ptr
)或不太理想的语义(auto_ptr
).
随着C++ 11 std::unique_ptr
即将到来,带来一个,人们会想到它终于结束了...我不是那么乐观.
只有少数几个主要编译器实现了大部分C++ 11,并且仅在最近的版本中实现.我们可以期待像QT和Boost这样的主要库愿意保留与C++ 03的兼容性一段时间,这在一定程度上排除了新的闪亮智能指针的广泛采用.
Rob*_*ess 12
你不应该远离智能指针,它们尤其适用于必须传递物体的应用程序.
库往往只返回一个值或填充一个对象.它们通常不具有需要在很多地方使用的对象,因此不需要它们使用智能指针(至少不在它们的界面中,它们可以在内部使用它们).
我可以把我们一直在研究的库作为例子,经过几个月的开发后,我意识到我们只在几个类中使用了指针和智能指针(占所有类的3-5%).
在大多数地方通过引用传递变量就足够了,只要我们有一个可能为null的对象,我们就会使用智能指针,而当我们使用的库强制我们使用时,我们会使用原始指针.
编辑(由于我的声誉,我无法发表评论):通过引用传递变量非常灵活:如果你想让对象只读,你可以使用const引用(你仍然可以做一些讨厌的强制转换,以便能够编写对象)但你可以获得最大程度的保护(智能指针也是如此).但我确实同意返回对象要好得多.
Qt毫无意义地重新发明了标准库的许多部分,试图成为Java.我相信它现在确实有自己的智能指针,但总的来说,它几乎不是设计的顶峰.据我所知,wxWidgets是在编写可用的智能指针之前设计的.
至于Boost,我完全希望他们在适当的地方使用智能指针.您可能必须更具体.
此外,不要忘记存在强制所有权的智能指针.如果API没有所有权语义,那么为什么要使用智能指针?