从函数返回一个对象C++
可以说我有一个变量指向我创建的对象。对于这个例子,可以说我有一个代表一张卡片的对象,该卡片有两个成员 - 排名和套装。从函数返回一个对象C++
接下来,可以说我初始化了我制作的物体结构,所以我现在有了一个拥有等级和套装的卡物。
我的问题是什么,如果我想返回,我创建了这个卡对象的函数: 我想要做这样的事情:
Card* playerCard = foo()
我知道玩家卡指向卡对象,所以不这意味着foo()也必须返回一个卡片对象?还有另一种解决这个问题的方法吗?
基本上我想我的功能来生成卡,并且playerCard应该等于生成的卡。我不知道返回一个对象是否是最直接的解决方案,这就是为什么我也问是否有其他解决方案。
感谢您的帮助!
我将逐渐从不良到好的方法。
首先,这是错误的方式做到这一点:
Card* foo() {
Card c;
return &c;
}
绝对不会这么做。 Card
c
将在foo
的末尾销毁,因此您返回的指针将指向无效的对象。
您可以做到这一点:
Card* foo() {
return new Card();
}
创建该卡由new Card()
具有动态存储持续时间,所以它不是在foo
结束时被销毁。因此返回的指针仍然指向该卡。然后你可以使用指针并且安全。
但是,这有另一个缺点。对于调用foo
的人不明确,但他们现在负责对指针返回delete
,以确保没有内存泄漏。相反,它是最好用智能指针清晰地传递所有权给调用者:
std::unique_ptr<Card> foo() {
return std::unique_ptr<Card>(new Card());
}
然而,更妙的是,如果你不需要动态分配的。为什么不只是返回Card
,并让它被复制出功能?你能做到像这样:
Card foo() {
return Card();
}
然后,而不是分配给一个指针,你会调用该函数,像这样:
Card c = foo();
这当然取决于你的要求,从而令此。如果要以多态方式使用Card*
,则需要使用其中一种指针方法。否则,您最终会切分您的衍生品Card
。
+1。你今天不可阻挡;) – 2013-03-26 21:27:02
“为什么不只是退还'卡'?”因为你可能想从'Card'继承,在这种情况下,你有很大的切片危险。 – 2013-03-26 21:31:27
@MattPhillips当然,这就是我问的原因。 :D – 2013-03-26 21:32:19
,如果你想返回一个指针,您可以使用动态内存分配,否则你的指针会的foo
执行后指向什么(见Dangling pointers):
Card* foo() {
Card* ret = new Card(...);
...
return ret;
}
上述代码的另一个版本将使用std::unique_ptr
从标准库中清除给你的代码的客户端程序员,你正在返回一个动态分配的指针。它是一个智能指针,因此它会在其作用域的末尾自动释放自己(不在函数结尾,因为它被复制到调用块)。
否则,如果你的对象/结构也不是很贵复制,你可以通过值导致复制返回它提出:
Card foo() {
Card ret(...);
...
return ret;
}
该副本很可能会在第二个代码示例中消失,因此不应考虑复制的费用。 – juanchopanza 2013-03-26 21:24:57
@juanchopanza,它真的取决于具体编译器的实现,不是吗? – Shoe 2013-03-26 21:26:12
是的,它的确如此,但是很难找到那些近期没有这样做的人。 – juanchopanza 2013-03-26 21:27:15
如果函数foo()返回一个指向一个卡对象是已创建,分配一个卡指针,它应该工作得很好。重要的是要记住,你有效地通过它相同的卡虽然,不是副本或任何东西。
你正在返回一个指向对象的指针,而不是对象。
我不知道这里你的问题是什么,所以我就只给你一个完整的例子:
struct card {int rank; int suit};
card make_a_card() {
return card{10,3};
}
int main() {
card a_card = make_a_card();
// a_card == card{10,3}
}
你很少想从一个函数返回原始指针。对速度没有必要(事实上,由于RVO和移动语义,实际上它最终会变得更慢),所以除了运行时多态性(即工厂方法)之外,没有什么理由要这样做。
我不确定你的所有要求,但我认为返回'Card',而不是'Card *',应该没问题。 – juanchopanza 2013-03-26 21:17:38