我有一个需要返回另一个类的新对象的函数,所以我想我需要在共享指针中保存它的返回对象。喜欢这个
X级内部;
Y* func(param)
{
return new Y(param);
}
我已尝试将其更改为
std::shared_ptr<Y> func(param)
{
std::shared_ptr<Y> y(new Y(param));
return y;
}
我不想返回本地对象,所以我该怎么办?
答案 0 :(得分:4)
我建议您std::shared_ptr
作为退货类型,return std::make_shared<Y>()
转让所有权。
这是一个可以帮助您的工作示例:
#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;
}
答案 1 :(得分:2)
您返回堆分配的对象,这意味着您转移了所有权。我建议你使用std::unique_ptr
作为返回类型
std::unique_ptr<Y> func(param)
{
return std::unique_ptr<Y>(new Y(param));
}
更好的是使用std :: make_unique(如果它已经可用,否则自己写)或 - 如果你使用shared_ptr - std :: make_shared。对于异常安全以及shared_ptr更高效的情况更好。
std::unique_ptr<Y> func(param)
{
return make_unique<Y>(param);
}
std::shared_ptr<Y> func(param)
{
return std::shared_ptr<Y>(param);
}
请注意,您的func
复制了参数。您可能希望使用转发来避免这种情况。
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)...));
}
答案 2 :(得分:0)
除了我建议std::unique_ptr
的答案之外,我想指出没有必要在堆上创建一个对象来从函数返回它。您可以按值返回新对象:
Y func(param)
{
Y result(param);
return result;
}
如果Y
可复制,这将(并且一直有效)。如果类不可复制,它将无法工作,如果它可以工作,它可能涉及复制对象。
虽然大多数编译器确实消除了多年的副本,但如果您返回一个未命名的临时对象,则标准C++17
现在必须使用该副本。这意味着即使您有一个不可复制和不可移动的对象,以下代码也将编译并返回一个新对象:
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);
}