Returning multiple data items from a function in C or C++ - c++

I am confused on a couple homework questions I have...
Can you return multiple data items from a function by using return()? Can a function only return one value, unless it is a pointer to an array?
I believe that the answer is that a function can return multiple data items by returning a structure. Then, returning a pointer to an array is not the only way - if that is a way?
But there seems to be a lot of discussion on this topic and so I want to make sure I have at least the basic idea correct: You can return multiple data items using a structure but using pointer (I don't understand this) will use memory more efficiently. Is this correct?

With C++0x/C++11 you can use this:
#include <string>
#include <iostream>
#include <tuple>
using namespace std;
tuple<int, unsigned, string, int> getValues()
{
return tuple<int, unsigned, string, int>(1, 2, "3", 4);
}
int main()
{
int a;
unsigned b;
string c;
int d;
tie(a, b, c, d) = getValues();
cout << a << ", " << b << ", " << c << ", " << d << endl;
return 0;
}
Compile it with
g++ tuple_test.cpp -std=c++0x -o tuple_test
And and if you run the programm it will output this:
1, 2, 3, 4
But it's better to use references like this (i would say):
void getValues(int& a, unsigned& b, string& c, int& d)
{
a = 1;
b = 2;
c = "3";
d = 4;
}
int main()
{
...
getValues(a, b, c, d)
...
}
Uch thats what I get for not reading the question carefully...
Can a function only return one value, unless it is a pointer to an array?
Yeah you only can return 1 single value, but this single value can include multiply values (struct, class, array).
You can return multiple data items using a structure but using pointer (I don't understand this) will use memory more efficiently. Is this correct?
True. But when you use pointers it depends on how you use it.
When you dynamic allocate it each function call it wont be very efficient and you would need to deallocate the memory manually after usage. When you use a global-array/struct it will be efficient. But can give you problems when you call the function multiply times.

In addition to what is already said in this thread, in C++11 you can return structures initialized using uniform initialization:
struct XYZ {
int x;
int y;
int z;
};
XYZ foo() {
return {1, 2, 3};
}
Personally I prefer returning structures with named members rather than tuples because the latter doesn't provide names for its members.

That is correct.
You can however "return" multiple items, by adding parameters that are passed by reference, then writing the multiple results to them.

A function can indeed only return one 'thing' with its return statement. That thing can, however, be a pointer (C & C++ arrays are simply pointers in disguise), a reference (a pointer which can't be reseated or array-indexed) or an object, which may encapsulate multiple things.
If you return a structure, you're passing back the entire structure. If you return a pointer or reference, you are returning only the address of the structure - so you had better not return a reference or pointer to a structure that goes out of scope when the function returns! Doing so invokes undefined behavior, which most likely (but not always) is a segmentation fault.

If you want a bigger picture about this read about passing parameters by value and passing by reference it also applies for returning parameters.
As you mentioned:
You can return multiple data items using a structure but using pointer (I don't understand this) will use memory more efficiently. Is this correct?
Lets say you have some structure:
struct BigStructure{
int array[1000];
double otherData[1000];
//... etc
};
and some method:
BigStructure workWhenCopying(BigStructure bigStruct){
// some work with a structure
return bigStruct;
}
This method illustrates the case when you pass parameters to the method and return it by value, which means that each time you call this method you are copying the method's argument into another place in memory. This copying takes time and when you have bigger structures it slows down your program run time thus it is more efficient to pass big structures by reference.
void workWithReference(BigStructure & bigStruct){
// do some work
}
In this case you are not copying whole data structure, just passing the address of the memory where this structure resides. You also don't need a return statement since changes to that structure object will be visible outside this method. But if you will reassign bigStruct to a new memory location it will be visible only within local method: workWithReference
I hope it's more clearer now;)

Related

C++ Pointer not being updated?

Not exactly sure how to word the title but I'll explain as best I can.
I have a program that originally used a 2D array of a set size and so it was defined as:
typedef char Map[Row][Col];
I'm now trying to dynamically allocate memory for it and it has now also become of variable size based on input. It's now defined as:
typedef char** Map;
In my main method, I originally had:
Map map;
readUserInput(map);
Basically readUserInput takes the map array as a parameter, and assigns values to it based on user input. The map then contains values and is used in other functions.
I've updated the readUserInput function so that it dynamically sizes the array and it allocates/deallocates memory for it. This works fine, but the problem comes from the fact that now in the main method, map is not being updated. The above code in main now looks like:
Map map = nullptr;
readUserInput(map);
but after running the readUserInput function, map is still null. Inside of the function, map is updated fine, so I'm not understanding the difference made between the changes.
What you pass to function is a pointer to array and fuction can't change it. But replacing array with pointer to pointer is incorrect in most case.Pointer to pointer suggest that have a 1D array of pointers. Which may (or may not) point to other arrays. Such data organization sometimes referred to as jagged arrays, because it allows each row to be of separate length. But on practtice jagged arrays and their subclass, sparse matrices, usually implemented as 1D array to avoid re-allocation.
To avoid decaying and to actually store a monolithic array in memory, you should use 1d array and, preferably, encapsulation for pointer arithmetic and reallocation, and then pass reference to object that stores all required states. Reference ensures that object is mutable by function ( a smart-pointer-less version for an example):
class Map
{
int rows, cols;
char *data;
public:
Map() : rows(), cols(), data(nullptr) {}
Map(int r, int c) : rows(r), cols(c), data(new char[r*c]()) {}
~Map() { delete[] data; }
void resize(int r, int c) {
if(rows == r && cols == c) return;
char* tmp = new char[r*c]();
if(data)
{
// copy old data here if required
delete[] data;
}
row = r; col = c;
data = tmp;
}
char& operator() (int r, int c) { return data[r*cols + c]; }
char operator() (int r, int c) const { return data[r*cols + c]; }
};
NB: this class requires a copy and move operations to be implemented if any copy must be allowed.
The function prototype would be:
void readUserInput(Map& map);
With such class you can do dynamic resizing, store its size, and address element as simple as this:
int main()
{
Map test(4, 5); // declaring and allocating memory
test.resize(3,3); // reallocating
test(1,1) = 3; // writing
//reading
std::cout << +test(1,1) << std::endl;
}
The function should accept the array by reference in the C terms like
readUserInput( &map );
when the function is declared like
void readUserInput( Map *map );
or in the C++ terms when the function is declared like for example
void readUserInput( Map &map );
and called like
readUserInput(map);
Instead of allocating dynamically arrays you could use the container std::vector<std::string>.
The code you have used is a pure C-style code, and is prone to many mistakes:
You use typedef instead of: using Map = char**;
You use a function which gets a pointer and fills it, which is more common in C than in C++.
You use raw pointer instead of smart pointers (added in C++11), which may cause a memory leak in the end.
I've updated the readUserInput function so that it dynamically sizes the array and it allocates/deallocates memory for it.
This means that now it should be a class named Map, since it should be able to allocate/deallocate, insert and remove values, and is a valid container. Actually, you are creating a type of std::vector here, and if you don't create it for you own learning process, I strongly suggest you to use the std containers!
It is possible to pass both pointer and references in C++, notice that:
You can pass a reference only if the value isn't nullptr.
When there should be a value, reference is recommended.
In this case, your function should look like
void readUserInput(Map* map);
and should be called using:
readUserInput(&map);

Creating a C++ array that can be several types

I have a function that returns a void*. Right now, when this function is completed, a UINT16* array is returned as the void*. The UINT16 array is created at the start of the method, but now I need a way to determine the type of array and create that type instead. For example, some data processing occurs and determines that an array of type int should be created, so an int array is created and returned. Other types like double and byte can also be created.
How do I go about achieving this?
My current code has
UINT16* data_out = new UINT16[arraySize];
I know I can create a large if/else or switch statement, but I'm wondering if there is a better way.
Something like that perhaps ?
This will not work, but thanks for the upvote. In fact it could work, but you'll have to know the type returned by Foo to be able to use it. But the type is determined inside Foo, that's a serious conception drawback. You should rethink the way you want this to work.
enum class ArrayType
{
Int,
Double
};
template <typename T>
T* CreateArray(size_t size)
{
T* t = new T[size];
return t;
}
void* Foo(param1, param2, etc..)
{
size_t size;
ArrayType type;
.. Do things to determine the type
switch(type)
{
case ArrayType::Int:
return CreateArray<int>(size);
case ArrayType::Double:
return CreateArray<double>(size);
default:
return 0;
}
return 0;
}
Uhm... sorry if this is more of a question than a comment... :| I can't comment rn.
If you want a core solution, you could create a linked list class that has different type outlets. Basically, instead of having just an UINT_64* next;, you would have:
int* nextInt;
double* nextDouble;
And so on and so forth. Then, if you want to tag a double along, you could just use the nextDouble outlet. To find which outlet to go to, just check if the int is pointing to anything; if not, go next. I know this seems like a REALLY annoying and bulky option, but I suppose it does the job.
I'm not sure why you have to use a practically untyped return value using void*, but let's suppose that there are reasons for it.
There are actually two issues, namely creating the array and using it then.
When creating an array of different types based on some logic, you somehow have to deal with if or switch(); how else would you express the logic determining the desired result type? But, if you like, you could also use something like result = malloc(nrOfItems*sizeOfItem), and determine sizeOfItem on any logic you like, even based on arithmetic calculations.
The more interesting or critical thing is how the caller shall use the result of the respective function, as accessing the elements of an array requires knowledge about the type or the size of the elements in it.
Suppose, for example, the following code:
void* getSomeItems() {
if (std::rand() > 100000)
return new char[200];
else
return new double[200];
}
int main() {
void* someItems = getSomeItems();
double c = ((double*)someItems)[199]; // Critical!
// how shall we know if element type is double?
// if rand() decided to create items of type char,
// this code accesses non allocated memory
...
So, unless your function can give back the information on which type has been created (and actually also the size of the array), the return value is almost needless.
I'd suggest not to use void* for this. If you know the type before calling the function, you could use templates, vectors, or other things. If you do not know type and/or size before calling, return a structure that - besides the allocated array - also provides type/size information.
BTW: do not forget to delete[] / free the result at the end.
Void * functions can be fun and do some very interesting things... (Sorry for linking a previous answer of mine, but it's the first example which came to me.) But they aren't safe, and have zero type checking...
So in your case, you only need a simple template function, and the auto keyword. Something like:
#include <iostream>
#include <iomanip>
template <typename T>
T * returnAnArray (int size) {
T * data_out = new T[size];
return data_out;
}
int main() {
int size = 3;
auto array = returnAnArray<double>(3);
for(int i=0;i<size;++i)
array[i] = 0;
for(int i=0;i<size;++i){
std::cout << std::setprecision(2);
std::cout << array[i] << std::endl;
}
delete [] array;
return 0;
}
I did have some fun, and did create a void * function:
template <typename T>
void * returnVoidPointerToArray(int size) {
return new T[size];
}
The function, when used, must be cast for it could return something:
auto chArray = (char*)returnVoidPointerToArray<char>(size);
But the output looks like:
5.00
5.00
5.00
ggg
ggg
ggg
Program ended with exit code: 0
Note how double are a single value, but the same function also initialized a 2d array of characters... Cool, right? Albeit, it's a dirtier, different way of templating functions.
And, like the commenter said, probably a good idea to use unique pointers. :)
And like the other commenter said, I cast the array to char* and got a char* array. :)

Variable as reference not staying

So i read this thread and many others:
Function does not change passed pointer C++
Yet i still can't solve my issue.
I have a function declared like this:
void test(list<int*> *listNodes){
int v=5;
(*listNodes).push_back(&v);
(*listNodes).push_back(&v);
(*listNodes).push_back(&v);
for(int a = 0; a < (*listNodes).size(); a ++){
std::list<int*>::iterator i = (*listNodes).begin();
advance(i, a);
int *totry = *i;
cout << *totry;
cout << ",";
}
}
Wich works, and prints fine, by the i mean: the listNodes variable has 3 elements, all 5's. However, when this functions returns, the values are not updated. By that, i mean that the variable has trash. I call this function in another one like this:
void create(list<int*> listNodes){
test(&listNodes);
for(list<int*>::const_iterator it=listNodes.begin();
it!=listNodes.end(); it++){
int *show=*it;
cout << *show << '\n';
}
}
Again, in this function, the cout will output memory garbage instead of outputting the 3 fives.
Any ideas on how should i proceed to, when the function test comes back, i have the list populated?
The problem I believe you're thinking about (as opposed to other problems in this code) is not actually what you're thinking. The list DOES maintain its values, the problem is that the values it has are pointing to garbage memory.
When you do this:
int v=5;
(*listNodes).push_back(&v);
(*listNodes).push_back(&v);
(*listNodes).push_back(&v);
You are putting three copies of the address of v into the list. You have declared v as a stack variable that only exists for the duration of this function. When you print the values pointed to by the elements of listNodes inside function test, that variable still exists in that memory location.
When you later print out the values pointed to by the elements of listNodes in function create, that variable has gone out of scope and has been used by something else, hence the garbage.
Here are two possible solutions to consider:
Use list<int> instead of list<int *>. If all you want to do is store a list of integers, this is the way to go.
If, on the other hand, you really need to store pointers to those integers, you'll need to allocate memory off the heap:
int* v = new int(); // allocate an int on the heap
*v = 5; // store 5 in that int
(*listNodes).push_back(v); // save the pointer to the allocated
// memory in *listNodes
etc
This is not very good in terms of modern c++, however, as you generally don't want to be handling raw pointers at all, but it illustrates the point I think you are struggling with.
In this code,
void create(list<int*> listNodes){
listNodes=teste(&listNodes);
… the formal argument listNodes is passed by value. That means that the function receives a copy of whatever was passed as actual argument in a call siste. Changes to this copy will not be reflected in the actual argument.
The call to teste won't call the test function, since it's a different name.
In a way that's good, because test is declared as a void function so it can't return anything.
But it's also bad, because it means that a very crucial piece of your code, the teste function that's actually called, isn't shown at all in your question.
The test function,
void test(list<int*> *listNodes){
int v=5;
(*listNodes).push_back(&v);
for(int a = 0; a < (*listNodes).size(); a ++){
std::list<int*>::iterator i = (*listNodes).begin();
advance(i, a);
int *totry = *i;
cout << *totry;
cout << ",";
}
printf("\n");
}
… has a lot wrong with it.
Starting at the top, in C++ the pointer argument
void test(list<int*> *listNodes){
… should better be a pass-by-reference argument. A pointer can be null. That doesn't make sense for this function, and the code is not prepared to handle that.
Next, in
int v=5;
(*listNodes).push_back(&v);
… the address of a local variable is pushed on a list that's returned. But at that point the local variable ceases to exist, and you have a dangling pointer, one that used to point to something, but doesn't anymore. If the caller uses that pointer then you have Undefined Behavior.
Next, this loop,
for(int a = 0; a < (*listNodes).size(); a ++){
std::list<int*>::iterator i = (*listNodes).begin();
advance(i, a);
… will work, but it needlessly has O(n2) complexity, i.e. execution time.
Just iterate with the iterator. That's what iterators are for. Iterating.
Summing up, the garbage you see is due to the undefined behavior.
Just, don't do that.

Derived vector: Perform operations

I have derived from std::vector<int> (I know I shouldn't, but I just wanted to test it). Now I can instantiate it and assign some values:
MyVector v(5);
v[0]=3;
I even can return the value:
cout << v[0];
But how can I access the value(s) if I want to do some operations within the class? Something like:
int func(int a){
return this->[0] + a; // EXAMPLE
}
As stated in the comments under the question:
return (*this)[0] + a; should work. – didierc 5 hours ago
Additionally, since vector lays out memory in a linear fashion (like an array) you can also access the memory which holds the values through a pointer, like so:
int *ptr = &(*this)[0];
// read an integer from the console into the 3rd element of the vector
scanf("%d", ptr + 2);
This can be useful if you have a vector of chars and you need to pass a char* to something like a string function, for example.
Be warned however, vector<bool> does not behave in the same way (the boolean values are stored internally in bitfields, not an array of bools, see http://isocpp.org/blog/2012/11/on-vectorbool).

C++: Return multiple NEW arrays

I think this is an easy issue, but it's driving me crazy: I want to return multiple arrays from one method, for which the calling method does not know their size in advance. So I have to create those Arrays inside the method (in contrast to just filling them) and I am not able to return them using return.
So what I would want is a method signature like this:
void giveMeArray(int[] *anArray)
Method signature has only one parameter to simplify the examples, please assume I could also have a signature like
void giveMeArrays(int[] *anArray, float[] *anotherArray)
Inside that method giveMeArray I would construct the array with
*anArray = new int[5];
and I would call that method using
int[] result;
giveMeArray(&result);
However, all this (starting with the method signature) is at least syntactically wrong. Please excuse that I don't have the compiler errors at hand by now, I'm pretty sure some of you will know what's wrong.
EDIT I know that std::vector would be the best (meaning cleanest) approach. However, folks, that wasn't the question.
Return a single vector (this is C++ afterall)
void giveMeArray(std::vector<int>& anArray)
{
anArray = std::vecotr<int>(5);
}
Return a vector of vectors:
void giveMeArray(std::vector<std::vector<int> >& anArray)
void giveMeArray(int **anArray);
int *result;
giveMeArray(&result);
std::vector<int> giveMeArray() {
std::vector<int> ret;
ret.resize(5);
return ret;
}
Nice resource cleanup, bounds checking in debug modes, etc. Good for all the family.
Consider wrapping the arrays in a class or struct.
struct Arrays {
int *ints;
int intCount;
double *doubles;
int doubleCount;
};
Arrays giveMeArrays() {
Arrays arrays;
arrays.ints = new int[10];
arrays.intCount = 10;
arrays.doubles = new double[20];
arrays.doubleCount = 20;
return arrays;
}
An alternative is to use a std::pair<> or a std::tuple<>, but in my experience any use of those eventually becomes a named type. The fact that they are all part of the result of your function suggests they may have enough coherence to be an object. Having a user-defined type makes it easier to pass the data around, and so to refactor code. You may even find that giveMeArrays() becomes a member function of this object.
Replacing ints/intCount with std::vector<int> would be better, if possible. If not, you may want to give Arrays more responsibility for memory management, disable copying while allowing moving, and so forth.