我有一些当前使用原始指针的代码,我想更改为智能指针。这有助于以各种方式清理代码。无论如何,我都有工厂方法可以返回对象及其调用者管理对象的责任。所有权不是共享的,因此我认为unique_ptr
是合适的。我返回的对象通常都来自单个基类Object
。
例如,
class Object { ... };
class Number : public Object { ... };
class String : public Object { ... };
std::unique_ptr<Number> State::NewNumber(double value)
{
return std::unique_ptr<Number>(new Number(this, value));
}
std::unique_ptr<String> State::NewString(const char* value)
{
return std::unique_ptr<String>(new String(this, value));
}
返回的对象通常需要传递给另一个函数,该函数对
Object
类型的对象(基类)进行操作。没有任何智能指针,代码就是这样。void Push(const Object* object) { ... } // push simply pushes the value contained by object onto a stack, which makes a copy of the value
Number* number = NewNumber(5);
Push(number);
将此代码转换为使用
unique_ptrs
时,我遇到了多态问题。最初,我决定简单地将Push
的定义更改为也使用unique_ptrs
,但这在尝试使用派生类型时会产生编译错误。我可以将对象分配为基本类型,例如std::unique_ptr<Object> number = NewNumber(5);
并将其传递给
Push
-当然可以。但是,我经常需要在派生类型上调用方法。最后,我决定让Push
对指向由unique_ptr
存储的对象的指针进行操作。void Push(const Object* object) { ... }
std::unique_ptr<Object> number = NewNumber(5);
Push(number.get());
现在,到发布原因。我想知道这是否是解决我遇到的问题的正常方法?相对于对象本身,让
Push
在unique_ptr
上进行操作是否更好?如果是这样,如何解决多态性问题?我认为仅仅转换ptrs是行不通的。需要从智能指针中获取基础指针吗?谢谢,对不起,如果问题不清楚(请告诉我)。
编辑:我认为我的Push函数有点含糊。它会复制基础值,并且实际上不会修改或存储输入对象。
最佳答案
您可能没有正确处理唯一性。
void push(std::unique_ptr<int>);
int main() {
std::unique_ptr<int> i;
push(i); // Illegal: tries to copy i.
}
如果对此进行编译,将琐碎
unique_ptr
的不变式,即只有一个unique_ptr
拥有一个对象,因为i
和push
中的本地参数都将拥有该int
,因此是非法的。 unique_ptr
仅可移动,不可复制。它与unique_ptr
完全正确处理的派生到基本转换无关。如果
push
拥有该对象,则使用std::move
将其移动到那里。如果不是,则使用原始指针或引用,因为这是您用于非所有者别名的方式。关于c++ - unique_ptr和多态,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/13288394/