简体   繁体   中英

Returning a shared_ptr

I have a function that needs to return a new object of another class, so I think I need to hold its return object in a shared pointer. Like this

Inside class X;

Y* func(param)
{
   return new Y(param);
}

I've tried changing it into

std::shared_ptr<Y> func(param)
{
   std::shared_ptr<Y> y(new Y(param));
   return y;
}

I don't want to return a local object, so what should I do ?

I recommend that you have std::shared_ptr as return type and return std::make_shared<Y>() to transfer ownership.

Here is a working example that might help you:

#include <memory>
#include <iostream>
#include <string>

class Y {
public:
    Y(const std::string& n)
    : name{n} {}

    std::string name;
};

std::shared_ptr<Y> func()
{
    return std::make_shared<Y>("new class");
}

int main()
{
    std::shared_ptr<Y> p_class = func();
    std::cout << p_class->name;
    // outputs: "new class"

    return 0;
}

You return a heap-allocated object which means you transfer ownership. I would suggest you use std::unique_ptr as the return type

std::unique_ptr<Y> func(param)
{
   return std::unique_ptr<Y>(new Y(param));
}

Even better is to use std::make_unique (if it is already available, otherwise write your own) or - if you use shared_ptr - std::make_shared. It is better for exception safety and in case of shared_ptr more efficient.

std::unique_ptr<Y> func(param)
{
   return make_unique<Y>(param);
}

std::shared_ptr<Y> func(param)
{
   return std::shared_ptr<Y>(param);
}

And be aware that your func copied the parameter. You may want to use forwarding to avoid this.

template<class T, class U>
std::unique_ptr<T> make_unique1(U&& u)
{
    return std::unique_ptr<T>(new T(std::forward<U>(u)));
}

template<class T, class... U>
std::unique_ptr<T> make_unique(U&&... u)
{
    return std::unique_ptr<T>(new T(std::forward<U>(u)...));
}

In addition to my answer suggesting std::unique_ptr , I want to point out that it is not necessary to create an object on the heap to return it from a function. You can just return the new object by value:

Y func(param)
{
   Y result(param);
   return result;
}

This will (and has always) worked if Y is copyable. It will not work if the class is not copyable, and if it works, it may involve copying the object.

While most compilers did eliminate the copy for years, this is now mandatory by the standard C++17 if you return an unnamed temporary object. That means that the following code will compile and return a new object even if you have a non-copyable and non-movable object:

class Y {
  public:
  Y(int i): value(i) {}
  Y(Y const&) = delete;
  Y(Y&&) = delete;
  Y& operator=(Y const&) = delete;
  Y& operator=(Y&&) = delete;

  int value;
};

Y foo(int i) {
  return Y(i);
}

void bar {
  Y y = foo(42);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM