我想从方法调用中返回一个signle对象,该方法调用包含在方法中创建的多个对象。
Results calculate() {
Foo f;
Bar b;
...
Results r(f, b);
return r;
}
class Results {
private:
?
public:
Results(Foo& f, Bar& b);
Foo? getFoo();
Bar? getBar();
}
a)Results
成员变量应该是指针吗?
private:
Foo* foo;
Bar* bar;
public:
Results(Foo& f, Bar& b) {
this->foo = &f;
this->bar = &b;
}
b)getFoo
应该Foo
,Foo&
还是Foo*
?
答案 0 :(得分:4)
使用C ++ 11的元组(或者提升,否则),你基本上是重新实现它们:
#include <tuple>
std::tuple<Foo, Bar> calculate() {
Foo f;
Bar b;
...
return std::make_tuple(f, b);
}
void test() {
Foo f;
Bar b;
std::tie(f, b) = calculate();
}
请注意,这可以很容易地扩展为返回2个以上的对象。这就是为什么我在另一个答案中提到std::tuple
而不是std::pair
。
答案 1 :(得分:2)
不,不要这样做。因为在calculate()
中,Foo f
和Bar b
是本地对象,当您从此函数返回时,它们将会消失。将f
和b
复制到Results
。
class Results {
private:
Foo foo;
Bar bar;
public:
Results(const Foo& f, const Bar& b) : foo(f), bar(b) {}
const Foo &getFoo() const { return foo; }
const Bar &getBar() const { return bar; }
}
更简单的方法是使用std::pair
并将其返回
std::pair<Foo, Bar> calculate() {
Foo f;
Bar b;
...
return std::make_pair(f, b);
}
答案 2 :(得分:1)
a)否。通过初始化calculate()
中的值,这些变量在函数完成执行时“死亡”。这样,之前初始化的指针将指向空白区域。
b)考虑到私人成员不是指针,你可以根据需要这样做。如果您希望数据“保留”在对象内部,您可以使用指针或引用(无关紧要)。否则采取“正常”变量。
答案 3 :(得分:0)
我仍然有点不确定你想要达到的目标,但目前你遇到了麻烦:
a和b在计算中的堆栈上,你基本上返回指向它们的指针。但是一旦计算完成并且a
和b
超出范围,你就会有疯狂的指针。那很糟糕。
如果您有更多的返回值,请创建智能指针并将其返回到对象中
或者将指针传递给a
和b
以计算并在计算中使用new
创建堆上的对象。但请注意,您必须自己删除它们,否则最终会导致内存泄漏。
所以基本上,如果result
中有两个以上的对象,那么添加一个智能指针,如std::auto_ptr
或std::shared_ptr
(或者如果你不使用C ++ 11 {{1} })
答案 4 :(得分:0)
a)结果成员变量应按值保存。否则,您将返回本地超范围数据的地址(或引用)。
b)getFoo应返回对象的const引用,或者在POD类型的情况下按值返回。
也就是说,考虑改变你的接口以接受Foo&amp;类型的i / o参数。和Bar&amp;,填充内部变量而不返回它们。这样可以避免返回值的两个副本,否则这是必要的。
您也可以用std :: tuple替换Results
类:
std::tuple<Foo,Bar> calculate() {
Foo f;
Bar b;
...
return std::tuple(f,b);
}
// client code:
Foo foo;
Bar bar;
std::tie(foo, bar) = calculate();
编辑:如果您不使用C ++ 11(对于std::tuple
),请考虑使用boost::tuple
。