unique_ptr and polymorphism

后端 未结 4 2031
深忆病人
深忆病人 2021-02-07 10:59

I have some code that currently uses raw pointers, and I want to change to smart pointers. This helps cleanup the code in various ways. Anyway, I have factory methods that retur

相关标签:
4条回答
  • 2021-02-07 11:24

    Initially I decided to simply change the definition of Push to use unique_ptrs too, but this generates compile errors when trying to use derived types.

    You likely did not correctly deal with uniqueness.

    void push(std::unique_ptr<int>);
    int main() {
        std::unique_ptr<int> i;
        push(i); // Illegal: tries to copy i.
    }
    

    If this compiled, it would trivially break the invariant of unique_ptr, that only one unique_ptr owns an object, because both i and the local argument in push would own that int, so it is illegal. unique_ptr is move only, it's not copyable. It has nothing to do with derived to base conversion, which unique_ptr handles completely correctly.

    If push owns the object, then use std::move to move it there. If it doesn't, then use a raw pointer or reference, because that's what you use for a non-owning alias.

    0 讨论(0)
  • 2021-02-07 11:29

    Well, if your functions operate on the (pointed to) object itself and don't need its address, neither take any ownership, and, as I guess, always need a valid object (fail when passed a nullptr), why do they take pointers at all?

    Do it properly and make them take references:

    void Push(const Object& object) { ... }
    

    Then the calling code looks exactly the same for raw and smart pointers:

    auto number = NewNumber(5);
    Push(*number);
    

    EDIT: But of course no matter if using references or pointers, don't make Push take a std::unique_ptr if it doesn't take ownership of the passed object (which would make it steal the ownership from the passed pointer). Or in general don't use owning pointers when the pointed to object is not to be owned, std::shared_ptr isn't anything different in this regard and is as worse a choice as a std::unique_ptr for Push's parameter if there is no ownership to be taken by Push.

    0 讨论(0)
  • 2021-02-07 11:39

    Here's a polymorphism example using unique pointer:

    vector<unique_ptr<ICreature>> creatures;
    
    creatures.emplace_back(new Human);
    creatures.emplace_back(new Fish);
    
    unique_ptr<vector<string>> pLog(new vector<string>());
    
    for each (auto& creature in creatures)
    {
        auto state = creature->Move(*pLog);
    }
    
    0 讨论(0)
  • 2021-02-07 11:42

    If Push does not take owenrship, it should probably take reference instead of pointer. And most probably a const one. So you'll have

    Push(*number);
    

    Now that's obviously only valid if Push isn't going to keep the pointer anywhere past it's return. If it does I suspect you should try to rethink the ownership first.

    0 讨论(0)
提交回复
热议问题