C++ 从C+;返回指针的推荐方法+;功能?
我有一个指针,它被传递给一系列函数,其中一个函数返回一个地址并将该地址分配给指针。在寻求有关Stackoverflow的帮助后,C++ 从C+;返回指针的推荐方法+;功能?,c++,pointers,C++,Pointers,我有一个指针,它被传递给一系列函数,其中一个函数返回一个地址并将该地址分配给指针。在寻求有关Stackoverflow的帮助后,collect\u file\u path方法有一个类型为QStringList**的参数。虽然我知道发生了什么,但我在自己的任何一本教科书中都没有遇到过这种符号,而且,它看起来很难看 我想要一些关于其他程序员如何实现我在下面代码中所做工作的建议/反馈。您会使用QStringList**还是其他方法 我希望我的要求有道理。我目前的代码是: void ThreadWork
collect\u file\u path
方法有一个类型为QStringList**
的参数。虽然我知道发生了什么,但我在自己的任何一本教科书中都没有遇到过这种符号,而且,它看起来很难看
我想要一些关于其他程序员如何实现我在下面代码中所做工作的建议/反馈。您会使用QStringList**
还是其他方法
我希望我的要求有道理。我目前的代码是:
void ThreadWorker::run()
{
QStringList* file_list;
collect_file_paths(&file_list);
}
void ThreadWorker::collect_file_paths(QStringList** file_list)
{
DirectorySearch ds;
*file_list = ds.get_file_names(_strPath);
}
QStringList* DirectorySearch::get_file_names(QString path)
{
QStringList *file_names = new QStringList;
traverse(path, file_names);
return file_names;
}
谢谢也可以通过指针引用,这是C++风格:
void ThreadWorker::collect_file_paths(QStringList*& file_list) <-- see *&
{
}
但与此相反,我仍然建议采用以下方法(更简单):
void ThreadWorker::run()
{
QStringList*文件列表=收集文件路径();
}
QStringList*ThreadWorker::收集文件路径()
{
DirectorySearch ds;//返回裸指针的问题是很容易导致对象内存泄漏。例如,如果函数中有任何内容抛出,则可能会发生这种情况;但也可能发生在调用方,在他们收到指针之前(例如,如果它被用作函数的参数,并且对另一个参数的求值抛出)
由于这些原因,最好在像“代码> STD::AutoMyPtR <代码> >(<代码> UNQuyGOPT/<代码>在即将到来的C++标准中)或<代码> Boo::/SyrdYPPTR <代码>(也可作为代码> STD::SyrdYPPTR <代码>,很快在您附近的标准库中)包装指针。。这些包装器将在适当的时候安全地删除包装的指针
但是,在这种特定情况下,您可以通过传递QStringList*
作为引用来管理,而无需使用QStringList**
。传递双指针在某些API中并不少见
在您的情况下,这似乎是不必要的。为什么collect\u file\u路径也不只是返回指针?只需按值返回。编译器可以对RVO、NRVO进行优化。您可以按值返回,因为不必要的副本将被优化掉。
这是一种清晰、异常安全的方法,也是我推荐的方法
void ThreadWorker::run()
{
QStringList file_list = collect_file_paths();
}
QStringList ThreadWorker::collect_file_paths()
{
DirectorySearch ds;
return ds.get_file_names(strPath_); // you should not use leading underscore in c++
}
QStringList DirectorySearch::get_file_names(QString path)
{
QStringList file_names;
traverse(path, &file_names);
return file_names;
}
顺便说一句,我认为Qt容器有写时拷贝优化,所以即使没有编译器优化,拷贝也会很便宜
如果您不信任(非常常见的)编译器优化,如RVO(heishe的评论),并且不使用诸如QStringList之类的写上复制对象,那么您应该在run()方法中创建实例,并将引用传递给其他函数。这不像我推荐的技术那样清晰,但仍然是异常安全的(至少是基本保证)
第三种解决方案是返回一个智能指针,如std::unique\ptr
。但在本例中,我看不出有任何理由需要额外的动态分配。如果您已使用新运算符分配内存,您可以只返回指针。另外,请记住对分配的内存使用delete。通常情况下,在析构函数方法(在本例中不是,因为您只在run方法中使用内存)
假设用户可以访问标头,但不能访问实现,则他/她不知道如何处理指针。如果您的函数是源函数(即使用new分配指针),则应返回auto_ptr。auto_ptr为:标准,从不抛出,专门设计用于执行此任务
您可以看看这个我首先会使用boost::shared\u ptr
place@rmflow:对于返回托管的动态分配资源的作业,我将使用auto_ptr
(unique_ptr
,如果可用),原因是如果调用方需要,它可以隐式转换为shared_ptr
,或者他们可以使用release()获取原始指针
如果他们有一些其他智能ptr,他们更喜欢boost::shared_ptr
。例如,他们可能更喜欢std::shared_ptr
(如果有的话),或者一些我从未听说过的其他智能指针。如果你返回shared_ptr
,他们最终会需要一个他们的_ptr
,这不是问题杰姆斯:好吧,我认为公平的说法是现代C++风格使得在裸指针的存在下编写异常安全代码几乎是不可能的。当然,这可以通过为智能指针编写更多代码来解决,但是我肯定会把整个事件描述为很难得到正确的。对于有经验的程序员。返回shared\u ptr
是反社会的,因为它阻止调用者使用任何其他智能指针类型来管理内存(shared_ptr的语义是,据您所知,返回它的函数保留了自己的引用。没有干净的方法从shared_ptr释放指针)。返回单所有者智能指针是可以的,IMO返回原始指针是可以的,前提是函数显然分配了资源,因此调用方显然需要将这些资源直接填充到他们自己选择的资源管理器中。哦,请注意“防止调用方使用任何其他智能指针类型”特别是,这意味着boost::shared\u ptr
和新的std::shared\u ptr
虽然几乎相同,但不会混合使用。因此,如果您认为您可能会从一个迁移到另一个,并且您的API强制执行其中一个或另一个,那么您可能会看到到处都会同时发生巨大的变化。不确定namespace boost{using std::shared_ptr;}
解决了这个问题,也许它解决了。我一直认为通过引用传递比通过值传递快得多。它们是,这就是为什么我“-1”给出了他的答案。他主要是r
void ThreadWorker::run()
{
QStringList* file_list = collect_file_paths();
}
QStringList* ThreadWorker::collect_file_paths()
{
DirectorySearch ds; //<---- ds uninitialized
return ds.get_file_names(_strPath); // for static function use ClassName::method() style
}
void ThreadWorker::run()
{
QStringList file_list = collect_file_paths();
}
QStringList ThreadWorker::collect_file_paths()
{
DirectorySearch ds;
return ds.get_file_names(strPath_); // you should not use leading underscore in c++
}
QStringList DirectorySearch::get_file_names(QString path)
{
QStringList file_names;
traverse(path, &file_names);
return file_names;
}
void ThreadWorker::run()
{
QStringList file_list;
collect_file_paths(file_list);
}
void ThreadWorker::collect_file_paths(QStringList& file_list)
{
DirectorySearch ds;
ds.get_file_names(strPath_, file_list);
}
void DirectorySearch::get_file_names(QString path, QStringList& file_list)
{
traverse(path, &file_list);
}
void ThreadWorker::run()
{
QStringList* file_list;
file_list = ds.get_file_names(_strPath);
//here we do something with file_list
//...
//Free the memory. You have to do this if the object pointed by file_list is not
//used anywhere else.
delete file_list;
}
QStringList* DirectorySearch::get_file_names(QString path)
{
QStringList *file_names = new QStringList;
traverse(path, file_names);
return file_names;
}