473,394 Members | 1,737 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,394 software developers and data experts.

How do you return a list? Best practices

Hi,
This may sound a odd question, but I wanted to know how you return a list of
data from a function. These are some of the ways I know how, and I was
wondering which method you normally use. This is more of a best practices
question rather than a technical one.

1) Return a list instance ie
std::list myFunction() {
std::list list();
return list;
}

This however does a lot of copying and isn't very efficient, but seems
conceptually the easiest.

2) Return a list pointer (or reference) ie
std::list * my Function() {
std::list *list = malloc(sizeof(std::list));
return list;
}

This only needs to copy a pointer, however this list must now be deleted. If
we passed the address of say a member variable (or global variable) then we
don't need to delete, but make sure it doesn't change before the caller is
finished using it.

3) Return a iterator ie,
std::list::iterator myFunction() {
std::list list;
return list.begin();
}

This has little copying again, but we also need to know the list.end() maybe
from another method.

4) Pass the list in
void myFunction(std::list &list) {
// Fill the list with stuff
}

Again little copying, sounds a good idea.
Each has pros and cons but this may sound like a silly question, but which
method is most "advisable" from a API point of view? For example if I was
writing a API for other developers to use, which would be the best?

Thanks very much
Andrew

P.S Would the answer to this question be any different if it was a set,
vector, or map?
Dec 12 '05 #1
15 25605
* Andrew Brampton:
Hi,
This may sound a odd question, but I wanted to know how you return a list of
data from a function. These are some of the ways I know how, and I was
wondering which method you normally use. This is more of a best practices
question rather than a technical one.

1) Return a list instance ie
std::list myFunction() {
Assuming you mean e.g. std::list<int>.

std::list list();
That's a declaration of a function 'list' returning a 'std::list'.

return list;
}

With a compiler that does NRVO optimization this (with errors mentioned above
fixed) is the best. Many compilers now do NRVO.

This however does a lot of copying and isn't very efficient
With NRVO it's actually the most efficient.

, but seems conceptually the easiest.
That also.
2) Return a list pointer (or reference) ie
std::list * my Function() {
std::list *list = malloc(sizeof(std::list));
return list;
}
Don't use malloc in C++, use 'new'.

This only needs to copy a pointer, however this list must now be deleted. If
we passed the address of say a member variable (or global variable) then we
don't need to delete, but make sure it doesn't change before the caller is
finished using it.
Use a std::auto_ptr< std::list<T> >.

3) Return a iterator ie,
std::list::iterator myFunction() {
std::list list;
return list.begin();
}
That's VERY BAD: you're returning a pointer to a local variable, and have
Undefined Behavior.
This has little copying again, but we also need to know the list.end() maybe
from another method.

4) Pass the list in
void myFunction(std::list &list) {
// Fill the list with stuff
}

Again little copying, sounds a good idea.
That's essentially what an NRVO optimization does, except the optimization
avoid the original initialization.
Each has pros and cons but this may sound like a silly question, but which
method is most "advisable" from a API point of view? For example if I was
writing a API for other developers to use, which would be the best?
The first, or the first plus the last (with the first as a wrapper for the
last, both offered to the client code).
P.S Would the answer to this question be any different if it was a set,
vector, or map?


No.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Dec 12 '05 #2

Andrew Brampton wrote:
Hi,
This may sound a odd question, but I wanted to know how you return a list of
data from a function. These are some of the ways I know how, and I was
wondering which method you normally use. This is more of a best practices
question rather than a technical one.


One way to do this is to use intrusive lists. Sketch:

template<class T>
struct list_node
{
list_node* next;
T value;
};

template<class T>
void delete_list(list_node<T>* node)
{
if(node)
{
delete_list(node->next);
delete node;
}
}

list_node<whatever>* create_my_list()
{
list_node<whatever>* head = new list_node<whatever>();
// attach other nodes to head->next
return head;
}

Dec 12 '05 #3
When I want to return a collection, I usually do it like this:

template<typename InIterator>
void GetCollection(InIterator it)
{
// return 1, 2, 3
*it++ = 1;
*it++ = 2;
* it++ = 3;
}

And call it like this:
std::list<int> myList;
GetCollection(std::back_inserter(myList));

--
Dag Henriksson

Dec 12 '05 #4

da************@hotmail.com wrote:
When I want to return a collection, I usually do it like this:

template<typename InIterator>
void GetCollection(InIterator it)
{
// return 1, 2, 3
*it++ = 1;
*it++ = 2;
* it++ = 3;
}


What would you do if this function were going to be exported from a
shared library?

Dec 12 '05 #5

Maxim Yegorushkin wrote:
da************@hotmail.com wrote:
When I want to return a collection, I usually do it like this:

template<typename InIterator>
void GetCollection(InIterator it)
{
// return 1, 2, 3
*it++ = 1;
*it++ = 2;
* it++ = 3;
}


What would you do if this function were going to be exported from a
shared library?


With shared libraries you will always have a problem as none of the STL
collections are portable across libraries, nor is std::string.

(You can use boost::shared_array instead of vector if you can be
certain that everyone is using the same implementation of boost).

Dec 12 '05 #6

Earl Purple wrote:
Maxim Yegorushkin wrote:
da************@hotmail.com wrote:
When I want to return a collection, I usually do it like this:

template<typename InIterator>
void GetCollection(InIterator it)
{
// return 1, 2, 3
*it++ = 1;
*it++ = 2;
* it++ = 3;
}
What would you do if this function were going to be exported from a
shared library?


With shared libraries you will always have a problem as none of the STL
collections are portable across libraries, nor is std::string.


This is often caused by the static linking of the C runtime library.
If you dynamically link to your basic runtime libraries (in ALL of the
libs being used) then everyone will use the same allocators and such
and the problem goes away. Of course this is a platform issue but
there you go...
(You can use boost::shared_array instead of vector if you can be
certain that everyone is using the same implementation of boost).


Dec 12 '05 #7
"Andrew Brampton" <an****@bramp.freeserve.co.uk> wrote:
std::list myFunction() {
std::list list();
return list;
}
Yuck. Wastes time and memory.

std::list * my Function() {
std::list *list = malloc(sizeof(std::list));
return list;
}
EWWW! Leaks memory like a sieve, if you're not very,
very careful.

std::list::iterator myFunction() {
std::list list;
return list.begin();
}
You cant name a list "list"! Also, passing an iterator to
a local that goes out of scope won't work.

void myFunction(std::list &list) {
// Fill the list with stuff
}


Yes. This is the way I always do it. But you still can't
name a list "list"! I don't think. Even if you can get
away with it for some reason, it's a bad idea. I'd write
that:

int MyFunction(std::list<Wombat> & Aardvark)
{
do stuff
maybe change contents of Aardvark
maybe delete or insert elements in Aardvark
maybe sort or re-order Aardvark
do more stuff
if (stuff went well) return 42;
else return 666;
}
--
Robbie Hatley
Tustin, CA, USA
lone wolf intj at pac bell dot net
home dot pac bell dot net slant earnur slant
Dec 12 '05 #8
Robbie Hatley wrote:
"Andrew Brampton" <an****@bramp.freeserve.co.uk> wrote:

std::list::iterator myFunction() {
std::list list;
return list.begin();
}

You cant name a list "list"! Also, passing an iterator to
a local that goes out of scope won't work.

So long as his variable isn't in the std:: namespace, why not?
I'll agree, though, that it's a bad idea.
Dec 12 '05 #9
Well thankyou to all that replied.

Other than my obvious mistakes you have given me some insight into the
"best" ways to do this.

Thanks again
Andrew

"Andrew Brampton" <an****@bramp.freeserve.co.uk> wrote in message
news:43***********************@ptn-nntp-reader02.plus.net...
Hi,
This may sound a odd question, but I wanted to know how you return a list
of data from a function. These are some of the ways I know how, and I was
wondering which method you normally use. This is more of a best practices
question rather than a technical one.

...

Thanks very much
Andrew


Dec 12 '05 #10

ro**********@gmail.com wrote:

[]
This is often caused by the static linking of the C runtime library.
If you dynamically link to your basic runtime libraries (in ALL of the
libs being used) then everyone will use the same allocators and such
and the problem goes away. Of course this is a platform issue but
there you go...


On Windoze only. There is no such problem on Linux.

Dec 13 '05 #11
I think the best way to written a list is for example

const list& myfunction() {

....
return list_xyz;
}

Dec 13 '05 #12

swesoc wrote:
I think the best way to written a list is for example

const list& myfunction() {

...
return list_xyz;
}


Yes, this is a good way to return a dangling reference.

Dec 13 '05 #13

Robbie Hatley wrote:
"Andrew Brampton" <an****@bramp.freeserve.co.uk> wrote:
std::list myFunction() {
std::list list();
return list;
}

Read Alf P Steinbach's post in this thread about Named Return Value
Optimisation. Quick summary:
Yuck. Wastes time and memory.


Not with most modern compilers.

Gavin Deane

Dec 14 '05 #14
de*********@hotmail.com wrote:
Robbie Hatley wrote:
"Andrew Brampton" <an****@bramp.freeserve.co.uk> wrote:
std::list myFunction() {
std::list list();
return list;
}

Read Alf P Steinbach's post in this thread about Named Return Value
Optimisation. Quick summary:

Yuck. Wastes time and memory.

Not with most modern compilers.

Gavin Deane


Is there a reliable way to find out if my compiler does NRVO?

I can think of:

a) Look at the compiler output. (I'd rather not.)

b) Given std::list<MyClass>, add a copy constructor to MyClass that does
a 'std::cout << "I'm being copied." << std::endl;' and watch what
happens. Might this be optimised away, even though NRVO is not happening?

c) Benchmark.

I wouldn't want to do something that is efficient on one compiler and
lousy on another. Hmm, are there circumstances where I might want NRVO
to not happen?

Thanks.

PJDM
Dec 15 '05 #15
On 2005-12-14, Peter Mayne <Pe*********@hp.com> wrote:
de*********@hotmail.com wrote:
Robbie Hatley wrote:
"Andrew Brampton" <an****@bramp.freeserve.co.uk> wrote:

std::list myFunction() {
std::list list();
return list;
}

Read Alf P Steinbach's post in this thread about Named Return Value
Optimisation. Quick summary:

Yuck. Wastes time and memory.

Not with most modern compilers.

Gavin Deane


Is there a reliable way to find out if my compiler does NRVO?

I can think of:

a) Look at the compiler output. (I'd rather not.)

b) Given std::list<MyClass>, add a copy constructor to MyClass
that does a 'std::cout << "I'm being copied." << std::endl;'
and watch what happens. Might this be optimised away, even
though NRVO is not happening?


This is not a good test since a compiler might realize that the
contructors have side effects and reject an optimization it would
otherwise have made.
c) Benchmark.

I wouldn't want to do something that is efficient on one
compiler and lousy on another. Hmm, are there circumstances
where I might want NRVO to not happen?


Don't write functions like these except when it is necessary, and
hope for the best. Alternatives are sometimes merely yucky, but
often actually incorrect. For example, do not try to manually
implement the NRVO when writing operator+.

--
Neil Cerutti
Dec 15 '05 #16

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
by: byrocat | last post by:
I'm chasing after a documetn that was available on one of the Microsoft websites that was titled somethign like "MS SQL Server Best Practices" and detailed a nyumber of best practices about...
136
by: Matt Kruse | last post by:
http://www.JavascriptToolbox.com/bestpractices/ I started writing this up as a guide for some people who were looking for general tips on how to do things the 'right way' with Javascript. Their...
2
by: Amelyan | last post by:
Could anyone recommend a book (or a web site) that defines best practices in ASP.NET application development? E.g. 1) Precede your control id's with type of control btnSubmit, txtName, etc. 2)...
10
by: jojobar | last post by:
Hello, I am trying to use vs.net 2005 to migrate a project originally in vs.net 2003. I started with creation of a "web site", and then created folders for each component of the site. I read...
14
by: dcassar | last post by:
I have had a lively discussion with some coworkers and decided to get some general feedback on an issue that I could find very little guidance on. Why is it considered bad practice to define a...
3
by: John Dalberg | last post by:
I am looking for an ASP.NET application on CodePlex which exemplifies best practices for the following: - Use of interfaces - Seperation of the UI, business and data tiers - Data Tier that uses...
24
by: Earl | last post by:
I have all of my data operations in a separate library, so I'm looking for what might be termed "best practices" on a return type from those classes. For example, let's say I send an update from...
12
by: Mark S. | last post by:
Hello, The app in question is lives on a Windows 2003 server with .NET 2.0 running IIS 6. The page of the app in question processes 2000 get requests a second during peak loads. The app uses...
33
by: John Salerno | last post by:
Is it possible to write a list comprehension for this so as to produce a list of two-item tuples? base_scores = range(8, 19) score_costs = print zip(base_scores, score_costs) I can't think...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.