我想从函数返回一个对象作为输出参数,但该对象没有默认构造函数,所以我不能这样做:
bool FindFlaggedObject(MyObject& myObject)
{
std::vector<MyObject> myObjects = GetSomeObjectList();
for (UINT i = 0; i < myObjects.size(); i++)
{
if (myObjects[i].Flag) {
myObject = myObjects[i];
return true;
}
}
return false;
}
void main()
{
MyObject myObject; // NOT ALLOWED - OBJECT HAS NO DEFAULT CONSTRUCTOR
if (FindFlaggedObject(myObject))
{
...
}
}
所以,看起来我应该在堆上返回它并使用shared_ptr实例进行管理,如下所示:
bool FindFlaggedObject(MyObject& myObject)
{
std::vector<MyObject> myObjects = GetSomeObjectList();
for (UINT i = 0; i < myObjects.size(); i++)
{
if (myObjects[i].Flag) {
myObject = new MyObject(myObjects[i]);
return true;
}
}
return false;
}
void main()
{
MyObject* myObjectPtr;
if (FindFlaggedObject(myObjectPtr))
{
std::shared_ptr<MyObject> myObject(myObjectPtr);
...
}
}
缺点是任何调用该方法的人都必须记住他负责解除对象的释放 将无构造函数的对象作为输出参数返回的最佳做法是什么?
答案 0 :(得分:5)
如果是对象,按值返回几乎总是最佳解决方案
支持复制(以及将在堆栈上声明的对象应该
一般支持复制)。如果功能失败,而不是总是失败
返回一个对象,您可以使用某种Fallible
或Maybe
类:
Fallible<MyObject>
FindFlaggedObject()
{
std::vector<MyObject> objects = GetSomeObjectList();
std::vector<MyObject>::const_iterator current = objects.begin();
while ( current != objects.end() && !current->flag ) {
++ current;
}
return current == objects.end()
? Fallible<MyObject>()
: Fallible<MyObject>( *current );
}
你可能会反思:如果GetSomeObjectList()总能返回一个 引用现有列表(而不是构建列表 在内部),你修改它以返回一个const引用,你可以 只需返回一个指针:
MyObject const*
FindFlaggedObject()
{
std::vector<MyObject> const& objects = GetSomeObjectList();
std::vector<MyObject>::const_iterator current = objects.begin();
while ( current != objects.end() && !current->flag ) {
++ current;
}
return current == objects.end()
? NULL
: &*current;
}
这是一个非常典型的C ++习语。
答案 1 :(得分:3)
而不是返回bool
并传入引用,函数返回一个智能指针,确保调用者不会忘记取消分配:
std::shared_ptr<MyObject> myObjectPtr = FindFlaggedObject();
if (myObjectPtr)
{
// Found flagged object.
}
std::shared_ptr<MyObject> FindFlaggedObject()
{
MyObject* result = nullptr;
std::vector<MyObject> myObjects = GetSomeObjectList();
for (UINT i = 0; i < myObjects.size(); i++)
{
if (myObjects[i].Flag) {
result = new MyObject(myObjects[i]);
break;
}
}
return std::shared_ptr<MyObject>(result);
}
答案 2 :(得分:2)
不使用out参数,而是返回一个值。由于该值是可选的,如bool的当前返回类型所示,您可以使用boost::optional
来实现此目的:
boost::optional<MyObject> FindFlaggedObject()
{
std::vector<MyObject> myObjects = GetSomeObjectList();
for (UINT i = 0; i < myObjects.size(); i++)
{
if (myObjects[i].Flag) {
return myObjects[i];
}
}
return boost::none;
}
答案 3 :(得分:0)
无需使用默认构造函数构造自动对象。 只需传递构造函数参数。
void main()
{
MyObject myObject (12);
if (FindFlaggedObject(myObject))
{
...
}
}
另一方面,为什么不这样做呢?
MyObject FindFlaggedObject()
{
std::vector<MyObject> myObjects = GetSomeObjectList();
for (UINT i = 0; i < myObjects.size(); i++)
{
if (myObjects[i].Flag) {
return myObjects[i];
}
}
return 0;
}
void main()
{
MyObject* res = FindFlaggedObject();
if (res != 0) {
...
}
}
您不必担心删除 res 只要 res 仍然是GetSomeObjectList中的成员