在C++ 0x(n3126)中,可以比较智能指针,无论是关系还是相等.但是,这样做的方式似乎与我不一致.
例如,shared_ptr定义operator<相当于:
template <typename T, typename U>
bool operator<(const shared_ptr<T>& a, const shared_ptr<T>& b)
{
return std::less<void*>()(a.get(), b.get());
}
Run Code Online (Sandbox Code Playgroud)
std::less与未指定的vanilla关系指针比较不同,使用提供关于指针值的总排序.
但是,unique_ptr定义相同的运算符:
template <typename T1, typename D1, typename T2, typename D2>
bool operator<(const unique_ptr<T1, D1>& a, const unique_ptr<T2, D2>& b)
{
return a.get() < b.get();
}
Run Code Online (Sandbox Code Playgroud)
它还以类似的方式定义了其他关系运算符.
为什么改变方法和"完整性"?也就是说,为什么shared_ptr使用std::less,而unique_ptr使用内置的operator<?为什么不shared_ptr提供其他关系运算符,比如unique_ptr?
我可以理解这两种选择背后的理由:
std::less谓词模板参数获得)但我不明白为什么选择会根据智能指针类型而改变.我错过了什么?
奖金/相关:std::shared_ptr似乎已经跟随boost::shared_ptr,后者省略了"按设计"的其他关系运算符(也是如此 …
我为Internet Explorer(BHO)编写附加组件,我正在使用CComPtr智能指针.我想知道:
void STDMETHODCALLTYPE CHelloWorldBHO::OnDocumentComplete(IDispatch *pDisp, VARIANT *pvarURL)
{
// Query for the IWebBrowser2 interface.
CComQIPtr spTempWebBrowser = pDisp;
// Is this event associated with the top-level browser?
if (spTempWebBrowser && m_spWebBrowser &&
m_spWebBrowser.IsEqualObject(spTempWebBrowser))
{
// Get the current document object from browser...
CComPtr spDispDoc;
hr = m_spWebBrowser->get_Document(&spDispDoc);
if (SUCCEEDED(hr))
{
// ...and query for an HTML document.
CComQIPtr htmlDoc2 = spDispDoc;
m_spHTMLDocument = spHTMLDoc;
}
}
}
我应该像使用m_spWebBrowser一样在SetSite函数中释放spHTMLDocument(就像之前提到的链接一样)?
CComPtr getObjects(CComQIPtr<IHTMLDocument3> …
弱指针就像智能指针,除了弱指针的引用不会阻止垃圾收集,弱指针必须在使用之前检查它们的有效性.
在我们的项目中(Linderdaum Engine http://www.linderdaum.com)中,我们使用了侵入式指针.为了避免循环引用和孤立孤岛,我们通过以下方式实现了弱入侵指针:
namespace LPtr
{
clPtr<iObject> GetObjectsGraphPtrWrapper( sEnvironment* Env, iObject* Obj, size_t Generation );
};
/// Intrusive weak smart pointer
template <class T> class clWeakPtr
{
public:
/// default constructor
clWeakPtr(): Env( NULL ), FObject( NULL ), FGeneration( 0 ) {}
explicit clWeakPtr( T* Ptr )
: Env( Ptr ? Ptr->Env : NULL )
, FObject( Ptr )
, FGeneration( Ptr ? Ptr->FGeneration : 0 ) {}
explicit clWeakPtr( const clPtr<T>& Ptr )
: Env( Ptr ? …Run Code Online (Sandbox Code Playgroud) 当您拥有unique_ptr由引用存储的自定义删除器时,对该案例进行成像:
struct CountingDeleter
{
void operator()(std::string *p) {
++cntr_;
delete p;
}
unsigned long cntr_ = 0;
};
int main()
{
CountingDeleter d1{}, d2{};
{
std::unique_ptr<std::string, CountingDeleter&>
p1(new std::string{"first"} , d1),
p2(new std::string{"second"}, d2);
p1 = std::move(p2); // does d1 = d2 under cover
}
std::cout << "d1 " << d1.cntr_ << "\n"; // output: d1 1
std::cout << "d2 " << d2.cntr_ << "\n"; // output: d2 0
}
Run Code Online (Sandbox Code Playgroud)
这是一个惊喜,我在上面的代码分配具有复制的副作用d2成d1.我仔细检查了一下,发现这种行为与[unique.ptr.single.asgn]中的标准一样 …
在我的方法中,创建一个Player对象,如:
Player player(fullName,age);
Run Code Online (Sandbox Code Playgroud)
我的老师给了我们一段带有构造函数的代码,该构造函数将shared_ptr带到了一个玩家对象.
//constructor of the class
SomeClass(const std::shared_ptr<Socket> client, std::shared_ptr<Player> player)
Run Code Online (Sandbox Code Playgroud)
让我们说我们想要调用SomeClass的构造函数并传递我们在堆栈上创建的玩家对象.
从堆栈对象创建shared_ptr是否安全/可能/好?
为了使问题更容易理解,我们假设我们有两个大的代码项目,并且我们想要合并它们,以便从另一个项目中调用一个项目的方法,我们是否应该重写所有文件以使用shared_ptr或独立地堆栈对象(对于那些方法而言)需要连接)或者我们应该只为堆栈对象创建一个shared_ptr.
为什么我不确定结果:
如果创建stackobject的范围结束但仍然使用shared_ptr,反之亦然.
stackobject在超出范围时会被删除,或者它是否仍然存活,因为仍然存在对该对象的引用(尽管在另一个类中)?
shared_ptr超出范围并尝试删除对象,即使stackobject引用它也可以吗?
注意:我知道我可以使用以下内容并传递播放器
shared_ptr<Player> player{ new Player {fullName,age} };
Run Code Online (Sandbox Code Playgroud) std::unique_ptr<int> ptr;
ptr = new int[3]; // error
Run Code Online (Sandbox Code Playgroud)
error C2679: binary '=' : no operator found which takes a right-hand operand of type 'int *' (or there is no acceptable conversion)
为什么这不编译?如何将本机指针附加到现有的unique_ptr实例?
避免使用未命名的shared_ptr临时值来保存输入; 要了解为什么这是危险的,请考虑以下示例:
void f(shared_ptr<int>, int);
int g();
void ok() {
shared_ptr<int> p(new int(2));
f(p, g());
}
void bad() {
f(shared_ptr<int>(new int(2)), g());
}
Run Code Online (Sandbox Code Playgroud)
函数ok遵循字母的准则,而bad构造临时shared_ptr,承认内存泄漏的可能性.由于函数参数是以未指定的顺序计算的,因此可以首先计算new int(2),g()second,如果g抛出异常,我们可能永远不会访问shared_ptr构造函数.<...>
通过使用boost/make_shared.hpp中定义的make_shared或allocate_shared工厂函数,也可以消除上述异常安全问题.这些工厂功能还通过合并分配提供了效率优势.
我想我会开始使用make_shared,但我想知道这一点建议是否仍然适用于C++ 11 shared_ptr.我问,因为我并不完全理解为什么投掷g()会阻止ctor被调用.
当我尝试以下操作时,GCC编译器会抱怨(见下文).class Face需要不完整,因为它包含指向class Element同样包含指针的指针class Face.换句话说,类之间存在循环依赖关系.我该如何解决?
错误:'sizeof'无效应用于不完整类型'Face'
class Face; // needs to be incomplete
class Element
{
std::vector < std::unique_ptr <Face> > face;
};
class Face
{
std::vector < std::unique_ptr <Element> > elm;
};
Run Code Online (Sandbox Code Playgroud) 我正在尝试检查a std::shared_ptr是否为空.这样做有什么区别
std::shared_ptr<int> p;
if (!p) { // method 1 }
if (p == nullptr) { // method 2 }
Run Code Online (Sandbox Code Playgroud) 原始指针可以指向堆栈或堆上分配的对象.
堆分配示例:
// heap allocation
int* rawPtr = new int(100);
std::cout << *rawPtr << std::endl; // 100
Run Code Online (Sandbox Code Playgroud)
堆栈分配示例:
int i = 100;
int* rawPtr = &i;
std::cout << *rawPtr << std::endl; // 100
Run Code Online (Sandbox Code Playgroud)
使用auto_ptr示例堆分配:
int* rawPtr = new int(100);
std::unique_ptr<int> uPtr(rawPtr);
std::cout << *uPtr << std::endl; // 100
Run Code Online (Sandbox Code Playgroud)
使用auto_ptr示例堆栈分配:
int i = 100;
int* rawPtr = &i;
std::unique_ptr<int> uPtr(rawPtr); // runtime error
Run Code Online (Sandbox Code Playgroud)
是否有"智能指针"用于指向堆上动态创建的对象?对于C++ 11,我们是否应该继续使用原始指针来指向堆栈分配的对象?谢谢.
smart-pointers ×10
c++ ×9
c++11 ×7
shared-ptr ×3
pointers ×2
unique-ptr ×2
bho ×1
com ×1
containers ×1
heap-memory ×1
rationale ×1
std ×1