This question already has answers here:
Is it better style to initialize a structure by passing a reference or returning it?
(4 answers)
Closed 6 years ago.
Which one is better if I have to return a string as well as an array from a function.
Create a structure containing string and array, populate that and return the instance of that structure.
Consider I have to send string "status" and an array "ids".
struct ReturnValues {
string status;
int ids[10];
};
use it as:
ReturnValues returnValues;
returnValues = func();
Consider that func() returns the object of ReturnValues
Pass one of them as referenced variable and return the other.
As:
int ids[10];
string status = func(ids);
Consider that func takes ids as referenced variable
string func(int& ids) {
//Some code
return status;
}
Pass both as referenced variables returning void.
As:
int ids[10];
string status;
func(ids, status);
Consider that func takes ids and status as referenced variables
void func(int& ids, string& status) {
//some code;
}
Strictly from a performance standpoint, it would give the compiler the most leverage to optimize if you do :
struct ReturnValues {
string status;
int ids[10];
};
and
ReturnValues returnValues = func();
Doing
ReturnValues returnValues;
returnValues = func();
will decrease performance since return-value optimization cannot take place : http://goo.gl/5Cfmw2
I would definitely go for the 1st version. Functions that modify their arguments tend to make the code more difficult to understand and test.
If you are worried about performance: Practically all compilers will use return value optimization here. So this should not be an issue, maybe except in some exotic cases.
Personally I would either group them together either into a predefined struct as you did or use std::pair or tuple if you don't want to define one explicitly. My feeling is that things that belong together belong together (if you'll forgive the tautology). Either way I would consider using std::array if the array length is fixed or std::vector (or some collection type) if not. Am not a fan of level C type arrays such astype A[10] I would probably just return them as a return value simply because it shows the intent "Get me one of these things with ints and strings in it" and let the compiler sort it out
Related
I'm trying to understand a Function/Method in a Library in order to port it to Java however some parameters don't make any sense to me and reading the source code the library is based on is not helping.
Function (Note the API has few comments (We can also ignore the calc handle since it's got a supplier method))
Ssr calc_ssr(CalcHandle *calc, NoteInfo *rows, size_t num_rows, float music_rate, float score_goal) {
std::vector<NoteInfo> note_info(rows, rows + num_rows);
auto skillsets = MinaSDCalc(
note_info,
music_rate,
score_goal,
reinterpret_cast<Calc*>(calc)
);
return skillset_vector_to_ssr(skillsets);
}
NoteInfo Struct
struct NoteInfo
{
unsigned int notes;
float rowTime;
};
MinaSDCalc
// Function to generate SSR rating
auto
MinaSDCalc(const std::vector<NoteInfo>& NoteInfo,
const float musicrate,
const float goal,
Calc* calc) -> std::vector<float>
{
if (NoteInfo.size() <= 1) {
return dimples_the_all_zero_output;
}
calc->ssr = true;
calc->debugmode = false;
return calc->CalcMain(NoteInfo, musicrate, min(goal, ssr_goal_cap));
}
Calc expected input file data (Only care about the #Notes: ...)
Pastebin
Question
What is NoteInfo in calc_ssr, I don't know any C or C++ so the *rows to me just seems like a pointer to a Noteinfo instance, however the MinaSDCalc methods requires an Array/Vector which using a pointer to a single instance doesn't make sense to me (pairing this with the fact that NoteInfo needs another parameter rowTime which I think is time of Note occurrence in the file which means that value must not be constant otherwise the produced result would be inaccurate)
Github Project: https://github.com/kangalioo/minacalc-standalone (The code alone may not explain enough but it's worth a try; best to look at API.h and discern what's used from there. Though I do warn you a lot of the Code is esoteric)
Sorry if this doesn't make much sense but I've been looking into this since June/July and this API is the closest abstraction from the bare C++ code I could find.
NoteInfo * rows here is pass by pointer. So, rows actually is a pointer to an instance of type NoteInfo. This is one of the ways to pass arrays in c++ to a function. Since arrays are contiguous in memory so we can just increment the pointer by one and get the next element of the array.
for example look at these three ways to do exactly one thing, parameter to pass an array to a function :-
1. void myFunction(int *param) {}
2. void myFunction(int param[10]) {}
3. void myFunction(int param[]) {}
Look into this link for more understanding : https://www.tutorialspoint.com/cplusplus/cpp_passing_arrays_to_functions.htm
Also search for pass by pointer and pass by reference to look into different ways of passing arguments in c++.
2.however the MinaSDCalc methods requires an Array/Vector which using a pointer to a single instance doesn't make sense to me: as to this question of yours, you can now see MinaSDCalc is actually getting an array and not a single instance as passing the pointer is also one of the ways of passing an array in c++.
This question already has answers here:
Which is more efficient: Return a value vs. Pass by reference?
(7 answers)
Closed 2 years ago.
I have been learning C++ and came across a function, but the return type was a vector.
Here is the code:
vector<Name> inputNames() {
ifstream fin("names.txt");
string word;
vector<Name> namelist;
while (!fin.eof()) {
Name name;
fin >> name.first_name;
fin >> name.last_name;
namelist.push_back(name);
}
return namelist;
}
name is part of a struct defined as:
struct Name {
string first_name;
string last_name;
bool operator<(const Name& d) const {
return last_name > d.last_name;
}
void display() {
cout << first_name << " " << last_name << endl;
}
};
What is the purpose of using vector< Name>inputName()? What is it doing?
And why can I just not create a void function and pass a vector through it?
I.e.:
void input(vector<Name>&v){
ifstream fin("names.txt");
string word;
while (!fin.eof()) {
Name name;
fin >> name.first_name;
fin >> name.last_name;
v.push_back(name);
}
}
Your question is basically: Do I return by value or do I use an output argument?
The general consensus in the community is to return by value, especially from C++17 on with guaranteed copy elision. Although, I also recommend it C++11 onwards. If you use an older version, please upgrade.
We consider the first snippet more readable and understandable and even more performant.
From a callers perspective:
std::vector<Name> names = inputNames();
It's clear that inputNames returns you some values without changing the existing state of the program, assuming you don't use global variables (which you actually do with cin).
The second code would be called the following way:
std::vector<Name> names;
// Other code
inputNames(names);
This raises a lot of questions:
does inputNames use the names as input or does it extend it?
if there are values in names, what does the function do with it?
does the function have a return value to indicate success?
It used to be good practice when computers were slow and compilers had troubles optimizing, though, at this point, don't use it for output arguments.
When do you use the last style: if you want an in-out argument. In this case, if you intend to append, the vector already had data, and that actually makes sense.
This basically mirrors the mathematical definition of a function as...
...a relation that associates an input to a single output.
While you could write void functions that modify their parameters, this has disadvantages:
Expression of intent. Consider a function taking multiple parameters. Which ones are input, which ones are output?
Clarity of purpose. A function modifying multiple values at once is usually (not always) attempting to do too many things at once. Focussing on one return value per function helps with keeping your program logic under control.
RAII. You can't use a void function to initialize a variable, meaning you would have to declare that variable first (initialized to some "default" value), then initialize it to the desired value.
There are languages that work without return values, using "out parameters" instead. You can do it this way in C++ as well. But all in all, using return values as the one output of a function helps the structure of your program.
vector<Name> is the return value of the method. It will create a new object with a vector of the structs.
Your implementation is called "call by reference". It will pass the pointer to an existing vector. As a example, with the call by the reference implementation, you could call input(vector<Name>&v) multiple times and your preexisting vector will have multiple times the content. If you would to it with the vector return value, it would always create a new object with only one iteration of data.
I am working with propriety code in my iOS project and all I have access to is the header files for my project. How do you declare an array in C++ so that it will return an array when I make a call?
Here's the header file method,
short WI_GetIDsFromList(int32_t module, int32_t *idsArray, uint32_t *count);
How do you declare an array to received an array of in32_t? I keep getting a parameter error for returnedIdsArray when I make this call? It works perfectly fine for count? I tried making it into a pointer but it did not work?
//Array of ID's
int32_t returnedIdsArray[] = {};
// Array of ID's count
uint32_t count;
rc += WI_GetIDsFromList(mod, returnedIdsArray, &count);
Another Example
short dpCount;
//Get number of data points from the device
WI_GetDatapointCount(modIDHDS, &dpCount);
//dpCount now has returned value of method WI_GetDatapointCount
NSLog#"%d", int(dpCount);
I think Mochi's question is how to declare the array that it suits the need of the function given in the header. If I understand him right, he has no influence to the function taking the array as parameter.
Did you try:
int32_t returnedIdsArray[MaximumExpectedIds];
Maybe there is also a function in the API giving you the number of Ids that you could use to determine the array size.
You cannot pass an array in C or C++, because they will always decay to a pointer to the first element.
You can, however, pass a reference to an array. It retains its array type rather than decay to a pointer, so sizeof() will return the actual size of the array rather than the sizeof pointer, and so on.
void f(char(&charArray)[30])
{
}
Syntax is pretty ugly though. A type alias can help:
using CharArray30 = char(&)[30];
void f(CharArray30 charArray)
{
}
etc. It has restrictions, though. For example, you cannot pass arrays of a different size.
If you need your function to work with various sizes, you can use a function template with a non-type parameter for the size:
template <size_t SIZE>
void f(int32_t module, int32_t(&idArray)[SIZE])
{
// ...
}
I guess that what you are trying to do is to have the function output a set of int values where the length is not known at compile-time.
In C++ an array has a fixed size that must be known at compile-time. The concept of "runtime-sized array" is called vector in C++.
Also, it is more natural to use the return value for values being returned. Your code could look like:
std::vector<int> WI_GetIDsFromList(int32_t mod);
and the calling code could be:
auto values = WI_GetIDsFromList(mod);
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
I'm trying to optimize my code. I've heard that it's better not to use local variables and to reduce the number of function parameters, so currently the structure of my program looks like this:
using namespace std;
const string UPLOAD_LOCATION = "/uploads";
const int value = 100;
const int type = 0;
const int max_value = 255;
string var1, var2, var3;
void func1();
void func2();
void func4();
int main(int argc, char *argv[])
{
func1();
func2();
}
void func1()
{
//do something
}
void func2()
{
func4();
//do something
}
void func4()
{
//do something
}
Would it be more efficient if var1, var2 and var3 were local variables in main function, so I'd pass them as arguments to the functions? I mean something like this:
using namespace std;
const string UPLOAD_LOCATION = "/uploads";
void func1();
void func2();
void func4();
int main(int argc, char *argv[])
{
const int value = 100;
const int type = 0;
const int max_value = 255;
string var1, var2, var3;
var1 = func1(var2, value, type, max_value);
var3 = func2(var2);
}
string func1(string &var2)
{
//do something
}
void func2(string &var2)
{
func4(var2);
//do something
}
void func4(string &var2)
{
//do something
}
If yes, is it better to pass them by reference or by value? For example lets say the function stores the result in string s, then which choice should I make:
a) void func( string in, string &result )
or
b) string func( string in )
Do not make all your locals and parameters globals
No...just...stop.
Make your code understandable to yourself and other human beings. That should be your goal. That's what you can do that a computer cannot.
Let your compiler optimize things. That's what it can do way better than you. If things will run much faster with certain variables not put on the stack, your compiler should be quite capable of recognizing that.
If you want more specific design goals when creating classes and methods, try to minimize coupling and maximize cohesion. Often times, you will even find that you get efficiency for free when you do this.
If the result isn't fast enough to meet requirements, with your compiler's optimization settings full out, only then should you really concern yourself with hand-optimizing. In this case, you get a profiler and actually measure what parts of your code are wasting the most time, and fix those parts. That way you don't stumble around punching at nothing like a blind boxer.
I'll take a stab at a couple of the questions
In the past it has always been better to pass by reference then value if you are not worried about the method you are calling modifying the value. IF you pass by value it has to do a copy construct, if you pass by reference it's just passing a pointer.
That said, C++ 11 is smarter and more efficient with the pass by value. So this is no longer a hard and fast rule. See this article for more info.
IN reference to your last question about having your value returned in as a parameter or the output of the method. This article is good at pointing out the pros and cons
Premature optimization is root of all evil
First and foremost make your program readable. Then make it work and only then and only if necessary optimize it. First optimize it on algorithm level, then run through profiler, find where your program spends most of the time and optimize that.
To your question:
void func( string in, string &result );
void func( string in );
Let's look which way is more readable to call such a function:
string str;
func( "foobar", str );
vs:
string str = func( "foobar" );
Can you guess at least in which case it is easier to understand that str is modified after func() call? As for optimization C++ committee did a great job to make more natural way of passing and returning values to/from functions as efficient as their less readable equivalent. So stop worry about what does not really matter and focus on what is necessary to write a good program.
I'm trying to optimize my code. I've heard that it's better not to use local variables and to reduce the number of function parameters
It is better to not use global state (variables and objects) and to reduce number of function parameters (where this makes sense). Your confusion here seems to come from the idea that this "it's better" means "it's better for efficiency reasons".
You will not optimize the speed (or memory footprint) of your code by reducing global state and number of function parameters. Instead, you will compartimentalize functionality and reduce interependency of various modules in your application making it easier to read, maintain and extend.
Would it be more efficient if var1, var2 and var3 were local variables in main function, so I'd pass them as arguments to the functions?
No. This has nothing to do with efficiency (but your second example of the same code is much easier to read).
Is it possible to get access to an individual member of a struct or class without knowing the names of its member variables?
I would like to do an "offsetof(struct, tyname)" without having the struct name or member variable name hard coded amoungst other things.
thanks.
Sure. If you have a struct and you know the offset and the type of the member variable, you can access it using pointers.
struct my_struct {
int member1;
char member2;
short member3;
char member4;
}
...
struct my_struct obj;
short member3 = *((short*)((char*)&obj + 5));
That'll get the value of member3, which is 5 bytes on from the start of obj on an x86 computer. However, you want to be careful. First of all, if the struct changes, your data will be garbage. We're casting all over the place, so you get no type safety, and the compiler won't warn you if something's awry. You'll also need to make sure the compiler's not packing the struct to align variables to word boundaries, or the offset will change.
This isn't a pleasant thing to do, and I'd avoid it if I were you, but yes, it can be done.
C and C++ are compiled languages without built-in "reflection" features. This means that regardless of what you do and how you do it, one way or another the path will always start from an explicit hard-coded value, be that a member name or an compile-time offset value. That means that if you want to select a struct member based on some run-time key, you have no other choice but to manually create a mapping of some kind that would map the key value to something that identifies a concrete struct member.
In C++ in order to identify a struct member at run-time you can use such feature as pointers-to-members. In C your only choice is to use an offset value.
Another issue is, of course, specifying the type of the members, if your members can have different types. But you provided no details about that, so I can't say whether you need to deal with it or not.
We had a similar problem some years ago: A huge struct of configuration information that we wanted to reflect on. So we wrote a Perl script to find the struct, parse its members, and output a C++ file that looked like:
struct ConfField
{ const char* name;
int type;
size_t offset;
};
ConfField confFields[] = {
{ "version", eUInt32, 0 },
{ "seqID", eUInt32, 4 },
{ "timestamp", eUInt64, 8 },
// ... lots more ...
{ 0, 0, 0 }
};
And we'd feed the script with the output from gcc -E.
Nowadays, I understand that gccxml can output an XML file representing any C++ source that gcc can compile, since it actually uses the g++ front end to do the parsing. So I'd recommend pairing it with an XML-parsing script (I'd use Python with the lxml library) to find out everything you ever wanted to know about your C++ source.
Somewhere in your code you need to reference the data member in the struct. However you can create a variable that is a pointer to a struct data member and from then on you no longer need to reference it by name.
struct foo
{
int member1;
int member2;
};
typedef int (foo::*intMemberOfFoo);
intMemberOfFoo getMember()
{
if (rand() > RAND_MAX / 2) return &foo::member1;
else return &foo::member2;
}
foo f;
void do_somthing()
{
intMemberOfFoo m = getMember();
f.*m = 0;
}
The technical answer is 'yes' because C++ is Turing-complete and you can do almost anything if you try hard enough. The more practical answer is probably 'no' since there is no safe and easy way of doing exactly what you want.
I agree with GMan. What exactly are you trying to do that makes you think you need this technique?
Well you will have to set up some stuff first, but it can be done. Expanding on Samir's response
struct my_struct {
int member1;
char member2;
short member3;
char member4;
}
you can create a table of offsets:
my_struct tmp;
int my_struct_offsets[4]={
0,
(char*)&(tmp.member2)-(char*)&(tmp.member1),
(char*)&(tmp.member3)-(char*)&(tmp.member1),
(char*)&(tmp.member4)-(char*)&(tmp.member1)
}
this will take into account different alignments on different systems