Recommended way to return a pointer from a C ++ function?

I have a pointer that is passed to a series of functions, where one function returns an address and assigns that address to a pointer. After finding some help on Stackoverflow, the collect_file_path method has a parameter of type QStringList** . Although I understand what is happening, I have not come across these notations in any of the books that I have, plus it looks ugly.

I would like to get some tips / reviews on how other programmers will implement what I did in the code below. Are you using a QStringList** or some other method?

I hope that what I ask makes sense. My current code is:

 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; } 

thanks

+4
source share
7 answers

You can also pass a pointer reference, which is more suitable for C ++:

 void ThreadWorker::collect_file_paths(QStringList*& file_list) <-- see *& { } 

Now you do not need to pass the address of file_list :

 collect_file_paths(file_list); // simply pass it 

But instead, I still recommend the following approach (which is easier):

 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 } 
+2
source

The problem with bare pointer return is that it is fairly easy to complete a memory leak for an object. This can happen, for example, if something in your function throws; but it can also happen on the caller's side before they receive a pointer (for example, if it is used as an argument to a function, as well as evaluating another argument).

For these reasons, it's best to unique_ptr pointers in a smart pointer such as std::auto_ptr ( unique_ptr in the upcoming C ++ standard) or boost::shared_ptr (also available as std::shared_ptr , soon in the standard library near you). These wrappers will safely monitor the removal of the wrapped pointer when the time comes.

However, in this particular case, you can do without using QStringList** by passing QStringList* as a reference.

+3
source

Just return the value. The compiler can RVO, NRVO and you can swaptimize.

+2
source

You can return by value, as unnecessary copies will be optimized. This is a clear, safe exception, and my recommended way.

 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; } 

http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/

Btw. I think Qt Containers has a copy for recording optimization, so the copy will be cheap even without compiler optimization.

If you do not trust the (very common) compiler optimizations, such as RVO (heishe comment), and you do not use copy-on-write objects such as QStringList, you must create an instance in the run () method and pass a link to other functions. This is not as clear as my recommended technique, but it is still an exception (at least a basic guarantee).

 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); } 

The third solution is to return a smart pointer, for example std::unique_ptr<QStringList> . But I see no reason for additional dynamic allocation in this example.

+2
source

This may seem ugly, but it's not uncommon to pass a double pointer in some APIs.

In your case, this seems unnecessary. Why doesn't collect_file_paths just return a pointer too?

0
source

If you allocated memory with a new statement, you can simply return the pointer. Also, be sure to use deletion in the allocated memory. A good place for this would usually be in the destructor method (not in this case, since you only use memory in the run method).

 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; } 
0
source

Assuming that the user has access to the header, but not to the implementation, he / she has no idea how to handle the pointer. If your function is the source (aka highlight the pointer with a new one), you should return auto_ptr. auto_ptr: standard, never thrown away and not specifically designed to do the job.

Perhaps you look at http://www.gotw.ca/publications/using_auto_ptr_effectively.htm

0
source

All Articles