I have written this program, which sorts some ints using a functor:
#include<iostream>
#include<list>
#include<set>
using namespace std;
struct IntSorter
{
unsigned int comparisons;
IntSorter()
{
std::cout << "new intsorter" << std::endl;
comparisons = 0;
}
bool operator() (const int &a, const int &b)
{
std::cout << "c is " << comparisons << std::endl;
++comparisons;
std::cout << "c is now " << comparisons << std::endl;
return a<b;
}
};
int main(int argc, char *argv[])
{
list<int> my_list;
my_list.push_back(4);
my_list.push_back(3);
my_list.push_back(5);
my_list.push_back(1);
IntSorter s;
my_list.sort(s);
for (list<int>::iterator it=my_list.begin(); it!=my_list.end(); it++)
{
std::cout << *it << std::endl;
}
return 0;
}
The sorting works fine, but the part counting the number of comparisons gives a result I didn't expect:
./prog -a -b -c -d
new intsorter
c is 0
c is now 1
c is 0
c is now 1
c is 0
c is now 1
c is 1
c is now 2
c is 2
c is now 3
1
3
4
5
I was thinking the structure would be reused, counting and storing the number of comparisons. However, it appears to copy it, or some other behaviour as the numbers printed out go 1,1,1,2,3, instead of 1,2,3,4,5. What am I doing wrong?
You're on the right track. std::list::sort takes the function object by value. As it does its work, it passes a copy of your function object around which means that the comparisons member data is getting copied, too.
You're not doing anything wrong, it's just that you can't use a functor like this.
The easiest way to make std::list::sort do what you want is to embed a reference to an external counter object in your functor. On each comparison, forward a call to that counter object. After std::list::sort returns, you'll have the total in there.
You're not really doing anything wrong. The problem lies entirely in your expectation -- the sorter is passed by value, so there's a bare minimum of one copy made as you pass it. The sort function is free to make more copies as well (e.g. a recursive sort will probably pass a copy to each recursive invocation).
There's a simple lesson here: any such object should be cheap to create and/or copy.
As mention it is passed by value:
A simple solution is:
struct IntSorter
{
unsigned int& comparisons;
IntSorter(unsigned int& c)
:comparisons(c)
{}
// Other Stuff
};
// In main:
unsigned int count = 0;
my_list.sort(IntSorter(count));
Related
Here is my problem:
int addsomeStuff(std::ostream &cout, int b) {
cout << b;
return 2;
}
int main() {
int a = 1;
cout << a << addsomeStuff(cout, 3) << endl;
return 0;
}
Output: 312
Can Someone explain me the Output, i would expect the output more like 132
why is the compiler runs first the Function before making the operator.
How i run into this issue:
I have a container class which can hold data inside an bytearray.
Somehow the 'container.WriteConvert(..);' get inserted into bytearray before the integer called 'a'. Does anyone have an explaintation for that.
I could make the WriteConvert static or add an extra Line which would fix this problem, instead of returning an Container& but i am kinda intrested whats the reason the Compiler puts this in this order.
int a = 2;
Container container;
container << a << container.WriteConvert("TestString");
int b = 0;
container >> b;
cout << b;
// The ouput of 'b' is some stupid Data which is caused by WriteConvert.
The Reason i didnt wrote this WriteConvert static or outside of the Container class has some reason. I have also ReadConvert which i dont want to have multiline. If someone has another idea i am open for other solutions, without increasing line amount.
int b = 0;
string output
container >> b >> container.ReadConvert(output);
cout << b;
Pre C++17, the order of evaluation of the chained operator arguments' was unspecified. That means the execution could've first evaluated addsomeStuff(cout, 3) call (thus printing 3 first) and then proceed to print a and the returned value of addsomeStuff(cout, 3).
With C++17, the order of evaluation is well defined - left to right. That means that if your compiler correctly implements the C++17 standard, the only possible output is 132.
If you are stuck with a pre C++17 standard, you would need to first evaluate all the arguments and then use them in chained operator call or don't use chained operator calls:
int main() {
int a = 1;
cout << a;
cout << addsomeStuff(cout, 3) << endl;
return 0;
}
The former approach may alter the behaviour, but will be well-defined.
I have some issues getting my head around the idea of pointers. I know what they do in theory, but i have a problem understanding what they can actually be capable of. The basic exercises that i have seen are a bit vague in my opinion because they can be done without the actual subject. For example swapping two number, either by reference or by address.
#include <iostream>
using namespace std;
int main()
{
int a = 45, b = 35;
cout << "Before Swap\n";
cout << "a = " << a << " b = " << b << "\n";
int z = a;
a = b;
b = z;
cout << "After Swap with pass by reference\n";
cout << "a = " << a << " b = " << b << "\n";
}
//copied an example i saw online with pointers and modified it to get the
same result without needing them
One example on when using pointers could be better (assuming this is some sort of school context) would be if you want to make a function to swap the numbers instead of rewriting your code a lot.
void swap(int *a, int *b) {
int temp = *a;
*a = *b;
*b = temp;
return
}
If you tried using integers in the function instead of pointers, it'd swap the values locally, and not swap the variables in a greater context. What you could do to achieve the same results is use references instead (ie int &a, int &b), so you don't really need to use pointers, and in this example they aren't particularly useful.
Pragmatically, std::swap()is much more useful in modern c++, but the example above might be why the online tutorial uses pointers.
Pointers can be useful in other contexts, but I don't know if that's within the scope of your question, just perhaps what the tutorial was trying to achieve by using pointers.
Use the std::swap() method for swaping.
It is more efficient.
For your understanding if we write a function which swaps two values
so we have to pass the values by reference and not by value.
same is
the case with pointers.some time we need to swap value by pointers.
So if we pass values to this function from the main it will swap it.
void swap(int&,int&);
But here it won't work if we pass values to this function from the main.
void swap(int,int);
forgive me for asking such a simple question, but I couldn't connect the dots from previous answers on SO or other sites. I have read that arrays are passed by reference by default and elsewhere I have read that arrays decay to pointers when passed into functions. I am trying to pass an array to a function and modify it, but cannot reconcile the previous two statements. I am not sure whether I am passing in a pointer or reference to toBin and whether it even matters. The following code is my attempt at making changes to the b array in the toBin function.
When I print the modified array, I get a whole bunch of unexpected text much bigger than the original allocated array of size 11 eg 1000000000 submarine blahblahblah. My expected output is 1000000000.
void toBin(int x,char a[]){ //passed by reference by default
std::cout << a << std::endl;
for (int i=9;i>=0;i--){
if(pow(2,i)<=x){
x=x-pow(2,i);
a[9-i]='1'; //i-1 because char b[] is zero indexed
};
}
}
int main()
{
char c[]="submarine";
double combination = pow(2,sizeof(c)-1);
char b[11]={'0','0','0','0','0','0','0','0','0','0'};
toBin(512, b);
for (int i=0;i<combination;i++){
std::cout << *(b+i) << std::endl;
}
}
Basically you pass everything to the function well. Thing that broke your output it's loop itself.
double combination = pow(2,sizeof(c)-1);
...
for (int i=0;i<combination;i++){
std::cout << *(b+i) << std::endl;
}
Your combination variable can have value like 2^8. So you point by*(b+i) to the address going far beyond the allocated array. To repair it you need change your loop to that:
for (int i=0;i< sizeof(b);i++){
I am trying to return values (namely rows and columns) upon a file read, and since I will be reading in multiple files and getting the same variables from each file, I thought it will be better for me to write a function rather than copying and pasting duplicate codes.
Anyway, I am trying to return 2 values and to use them too, please see my code below:
#include <iostream>
#include <fstream>
using namespace std;
int r(string fn);
int main()
{
int a, b = r("input_a.txt");
cout << "a --- " << a << endl;
cout << "b --- " << b << endl;
}
int r(string fn)
{
ifstream fin01;
string file = fn;
fin01.open(file.c_str());
...
...
...
// Suppose I should be getting 2 for 'rows' and 3 for 'cols'
return rows, cols;
}
I got 0x7fff670778ec and 0x7fff670778e8 for my output instead...
Any pointers?
You cannot return two values from a function that is declared to have a single int as return type:
int r(string fn){
/*...*/
return rows,cols; // <-- this is not correct
}
Also the way you call this function is not behaving as you might expect:
int a, b = r("input_a.txt");
this declares two integers and initializes the second one with the return value of the function, but the first one stays uninitialized (see TerraPass answer for more explanation on the comma operator).
You basically have two options. First option is to pass references to the function and the function assigns the results to those references:
void r(string fn, int& rows,int& cols) {
/*...*/
rows = x;
cols = y;
}
and you call it like this:
int a,b;
r("someString",a,b);
However, in this way the caller has to "prepare" those return values. Imho it is more convenient to use the return value to return results from a function (sounds logical, no?). To do this you just have to define a type that encapsulates the two integers:
struct RowAndCol { int row;int col; };
RowAndCol r(string fn) {
/*...*/
RowAndCol result;
result.row = x;
result.col = y;
return result;
}
and call it like this:
RowAndCol rc = r("someString");
Note that you could also use a std::pair<int,int> instead of defining your custom struct (see e.g. molbdnilos answer). However, IMHO whenever you know exactly what is contained in the pair, it is better to give it a reasonable name (e.g. RowAndCol) instead of using a naked std::pair<int,int>. This will also help you in case you need to add more methods to the struct later (e.g you might want to overload the std::ostream& operator<< for your struct to print it on the screen).
PS: Actually your output does not look like it was produced by the code you are showing. Theses are some memory addresses, but in your code there is neither a pointer nor an address-of operator.
I guess you're used to Python (I peeked at your profile), but the comma does not create a pair in C++.
(You may not have thought about it that way, but you can only return one value from a Python function, too. If you "return two values", you're returning one pair.)
Fortunately, there are tuples in the standard library.
#include <iostream>
#include <fstream>
#include <utility>
std::pair<int,int> r(std::string fn);
int main()
{
std::pair<int, int> result = r("input_a.txt");
cout << "a --- " << result.first << endl;
cout << "b --- " << result.second << endl;
// Or,
int a = 0;
int b = 0;
std::tie(a, b) = r("input_a.txt");
cout << "a --- " << a << endl;
cout << "b --- " << b << endl;
}
std::pair<int, int> r(std::string fn)
{
std::ifstream fin01(fn);
// ...
return std::make_pair(rows, cols);
}
Functions in C++ cannot return multiple values of their return type via a return statement.
int a, b = r("input_a.txt");
...
return rows, cols;
These 2 lines don't do what you think they do.
The line int a, b = r("input_a.txt"); is equivalent to:
int a;
int b = r("input_a.txt");
That is, you declare variables a and b and initialize b to the return value of r("input_a.txt"), while a remains uninitialized.
The line return rows, cols; is equivalent to:
rows;
return cols;
...and is an example of comma operator, which evaluates its left operand (in your case, rows), discards the result, then evaluates its right operand (in your case, cols) and returns the result of this evaluation. So, in effect, your function r(), as it is now, always returns a single value, cols.
If you need to return more than one value from a function, you should consider accepting additional arguments as non-const references for you to store resulting values to, or changing the return type of your function to some struct, which would contain all of the values you want to return. You can find an example of both these approaches in #tobi303's answer.
Say I have the following code:
#include <iostream>
using namespace std;
int defaultvalue[] = {1,2};
int fun(int * arg = defaultvalue)
{
arg[0] += 1;
return arg[0];
}
int main()
{
cout << fun() << endl;
cout << fun() << endl;
return 0;
}
and the result is:
2
3
which make sense because the pointer *arg manipulated the array defaultvalue. However, if I changed the code into:
#include <iostream>
using namespace std;
int defaultvalue[] = {1,2};
int fun(int arg[] = defaultvalue)
{
arg[0] += 1;
return arg[0];
}
int main()
{
cout << fun() << endl;
cout << fun() << endl;
return 0;
}
but the result is still:
2
3
Moreover, when I print out the defaultvalue:
cout << defaultvalue[0] <<endl;
It turn out to be 3.
My question is, in the second example, should the function parameter be passed by value, so that change of arg will have no effect on defaultvalue?
My question is, in the second example, should the function parameter be passed by value, so that change of arg will have no effect on defaultvalue?
No.
It is impossible to pass an array by value (thanks a lot, C!) so, as a "compromise" (read: design failure), int[] in a function parameter list actually means int*. So your two programs are identical. Even writing int[5] or int[24] or int[999] would actually mean int*. Ridiculous, isn't it?!
In C++ we prefer to use std::array for arrays: it's an array wrapper class, which has proper object semantics, including being copyable. You can pass those into a function by value just fine.
Indeed, std::array was primarily introduced for the very purpose of making these silly and surprising native array semantics obsolete.
When we declare a function like this
int func(int* arg);
or this
int (func(int arg[])
They're technically the same. It's a matter of expressiveness. In the first case, it's suggested by the API author that the function should receive a pointer to a single value; whereas in the second case, it suggests that it wants an array (of some unspecified length, possibly ending in nullptr, for instance).
You could've also written
int (func(int arg[3])
which would again be technically identical, only it would hint to the API user that they're supposed to pass in an int array of at least 3 elements. The compiler doesn't enforce any of these added modifiers in these cases.
If you wanted to copy the array into the function (in a non-hacked way), you would first create a copy of it in the calling code, and then pass that one onwards. Or, as a better alternative, use std::array (as suggested by #LightnessRacesinOrbit).
As others have explained, when you put
int arg[] as a function parameter, whatever is inside those brackets doesn't really matter (you could even do int arg[5234234] and it would still work] since it won't change the fact that it's still just a plain int * pointer.
If you really want to make sure a function takes an array[] , its best to pass it like
template<size_t size>
void func (const int (&in_arr)[size])
{
int modifyme_arr[100];
memcpy(modifyme_arr, in_arr, size);
//now you can work on your local copied array
}
int arr[100];
func(arr);
or if you want 100 elements exactly
void func (const int (&arr)[100])
{
}
func(arr);
These are the proper ways to pass a simple array, because it will give you the guaranty that what you are getting is an array, and not just a random int * pointer, which the function doesn't know the size of. Of course you can pass a "count" value, but what if you make a mistake and it's not the right one? then you get buffer overflow.