我想知道如何从C ++函数返回一个新对象。例如,我有一个SQLite包装器,用于混合Objective-C,我将其修改为纯C ++。
所以,例如:
list<char*> * SqliteWrapper::RunQuery(const char *query)
{
list<char*> * result = new list<char*>();
//Process query
return result;
}
我在这里可以看到的问题是谁拥有这个对象?调用类或创建对象的类?更糟糕的是,这很容易发生内存泄漏。如果调用者对象没有删除新创建的对象,则应用程序将最终导致内存泄漏。
现在我想到这一点,这很有道理:
int SqliteWrapper::RunQuery(const char *query, list<char*>& result)
{
//Process query
return errorCode;
}
还有其他方法吗?我有一段时间以来一直是C#程序员,现在才开始大量使用C / C ++。
答案 0 :(得分:1)
许多程序员这样做:
如果它是一个返回的指针,我将被赋予对象的身份(它在内存中的位置是唯一的)我必须管理它。我有责任删除它。
(指针=我的工作)
然而,引用让你假装你正在传递对象,看看和使用。你不负责删除这些,其他的是。
BUT:
“Naked pointers”对于像这样的代码(这是非常主观的)可能不赞成所以有些人会说使用“unique_ptr”,这些可以被移动,并删除它们在删除时指向的内容(除非这些东西是移出他们),通过返回一个而不使用它,它将被删除。
(告诉我,如果你想要我这样做,请参阅“shared_ptr”如果有多个东西有指针,这将删除指向它的最后一个shared_ptr被删除时指向的内容)
附录1
unique_ptr<list<char*>> SqliteWrapper::RunQuery(const char *query)
{
list<char*> * result = new list<char*>();
//Process query
return make_unique<list<char*>>(result);
}
请记住,您只能移动,而不能复制unique_ptrs
答案 1 :(得分:0)
好。你是对的。
第一个例子是一个糟糕的风格,因为在这样的代码中几乎不可读,并且很难跟踪其中的错误。
通常人们使用第二种方法参考。 以同样的方式使用指针,在函数调用之前分配返回对象。
第三种方法是使用类而不是函数。如果您的函数使用许多参数执行复杂的过程,这很方便。在这种情况下,您将结果存储为类的数据成员,并且所有权显而易见:
class SqliteWrapper {
...
class ProcessQuery {
public:
ProcessQuery():fQ(0),fP1(0){}
SetQuery(const char *query){ fQ = query; }
SetP1(int p1){ fP1 = p1; }
...
list<char*> GetResult(){ return fR; } // copy
int Run();
private:
const char *fQ;
int fP1;
...
list<char*> fR;
}
...
}
int SqliteWrapper::Process::Run()
{
//Process query
return errorCode;
}