我的方法是:
class SomeClass
{
std::vector<std::unique_ptr<MyObject>> myObjects;
public:
void takeOwnership(MyObject *nowItsReallyMyObject)
{
myObjects.emplace_back(std::move(nowItsReallyMyObject));
}
};
我是在正确地做所有事情还是有更好的解决方案?
答案 0 :(得分:4)
move
是多余的。
我自己,我这样做:
void takeOwnership(std::unique_ptr<MyObject> nowItsReallyMyObject)
{
myObjects.emplace_back(std::move(nowItsReallyMyObject));
}
因为我希望将unique_ptr
所有权语义移到&#34; out&#34;尽可能。
我可能会写这个效用函数:
template<class T>
std::unique_ptr<T> wrap_in_unique( T* t ) {
return std::unique_ptr<T>(t);
}
所以来电者可以:
foo.takeOwnership(wrap_in_unique(some_ptr));
但更好的是,可以将unique_ptr
语义的边界推到合理的范围内。
我甚至可以这样做:
template<class T>
std::unique_ptr<T> wrap_in_unique( T*&& t ) {
auto* tmp = t;
t = 0;
return std::unique_ptr<T>(tmp);
}
template<class T>
std::unique_ptr<T> wrap_in_unique( std::unique_ptr<T> t ) {
return std::move(t);
}
可让来电者将T*
转换为unique_ptr
更容易。他们的所有T*
- &gt; unique_ptr<T>
现在都包含在std::move
中,并将源指针归零。
所以,如果他们有
struct I_am_legacy {
T* I_own_this = 0;
void GiveMyStuffTo( SomeClass& sc ) {
sc.takeOwnership( wrap_in_unique(std::move(I_own_this)) );
}
};
代码可以转换为:
struct I_am_legacy {
std::unique_ptr<T> I_own_this;
void GiveMyStuffTo( SomeClass& sc ) {
sc.takeOwnership( wrap_in_unique(std::move(I_own_this)) );
}
};
它仍然编译和工作相同。 (与I_own_this
的其他交互可能必须更改,但其中一部分已经与unique_ptr兼容)。
答案 1 :(得分:2)
您应该从一开始就接受unique_ptr
:
class SomeClass
{
std::vector<std::unique_ptr<MyObject>> myObjects;
public:
// tells the world you 0wNz this object
void takeOwnership(std::unique_ptr<MyObject> myObject)
{
myObjects.push_back(std::move(myObject));
}
};
通过这种方式,您可以清楚地了解自己的所有权,并且还可以帮助其他程序员避免使用原始指针。
进一步阅读:CppCoreGuidelines R.32