Home > Net >  Return unique_ptr where the underlying object can't be changed
Return unique_ptr where the underlying object can't be changed

Time:09-09

I am trying to replace raw pointers with smart pointers.

class MyObj {
public:
    MyObj() {
        rawContainer = new BigObj();
    }       
    
    const BigObj* GetRawObj() {
        return rawContainer;
    }

private:
    BigObj* rawContainer;
};

When I call auto rawObj = myObj.GetRawObj() I avoid copying BigObj and can only call the functions marked const, so I can't modify it's content.

class MyObj {
public:
    MyObj() {
        std::unique_ptr<BigObj> ptr(new BigObj());
        container = std::move(ptr);
    }

    const std::unique_ptr<BigObj>& GetObj() {
        return container;
    }

private:
    std::unique_ptr<BigObj> container;
};

This time, with auto smartObj = myObj.GetObj(); I can access non-const methods of smartObj.

I understand the definition const std::unique_ptr<BigObj>& GetObj() is making the reference constant, and not the underlying object, but changing it to const std::unique_ptr<const BigObj>& GetObj() creates a compiler error.

Is there a sensible way to do this? I've seen suggestion of just returning a raw pointer from the smart pointer and using it like in the first example. The actual object in MyObj can't be const since it can actually be modified by some methods.

CodePudding user response:

It is perfectly valid to declare const std::unique_ptr<const BigObj>& GetObj(). The problem must be somewhere else.

#include <memory>

class BigObj
{

};

class MyObj 
{
public:
    MyObj(): container(std::make_unique<BigObj>()) {}

    auto GetObj() -> const std::unique_ptr<const BigObj>&
    {
        return reinterpret_cast<const std::unique_ptr<const BigObj>&>(container);
    }

private:
    std::unique_ptr<BigObj> container;
};

auto main()->int
{
    MyObj obj;
    obj.GetObj();
}

https://onlinegdb.com/xzHzI4GgM

CodePudding user response:

Like the commenters above is suggesting. Just return a raw pointer. There is no reason to return a reference to the unique_ptr below.

#include <memory>

struct BigObj {
    int bigData = 1000;
};

class MyObj {
public:
    const BigObj& getObj() const {
        return *container;
    }

    // Alternative if you want a pointer instead of a reference
    // (you probably don't if you know that the pointer is non null)
    //const BigObj* getObj2() const {
    //    return container.get();
    //}

private:
    std::unique_ptr<BigObj> container = std::make_unique<BigObj>();
};

int main() {
     auto myObj = MyObj{};

     auto &ref = myObj.getObj();
}

Note: There is syntax if you want to be able to move a ptr out of the object, but I guess that that is not a part of the question.

  • Related