C++ this and constant object - c++

could you tell me why this code works? There is overloaded operator() which is used by replace_if algorithm. In main function I've created constant object of IsEqual class so only constant function member should be used. Somehow constancy isn't working and that operator is called.
#include <iostream>
#include <vector>
#include <algorithm>
class IsEqual {
int value;
public:
IsEqual(int v) : value(v) {}
bool operator()(const int &elem){
this->value=6;
return elem == value;
}
};
int main()
{
const IsEqual tst(2);
std::vector<int> vec = {3,2,1,4,3,7,8,6};
std::replace_if(vec.begin(), vec.end(), tst, 5);
for (int i : vec) std::cout << i << " ";
std::cout<<std::endl;
}
result: 3 2 1 4 3 7 8 5

std::replace_if will make its own copy of the tst object. It is not required to restrict it to be const.
If you want to use the original object in the algorithm, you can use an std::reference_wrapper. Since it would be referring to a const object,this would result in a compiler error because it would require the operator to be const:
std::replace_if(vec.begin(), vec.end(), std::ref(tst), 5);

Related

Vector of objects without a default constructor and iterator

I am learning to use C++ vectors, and I can't quite understand the output of the following program:
#include <iostream>
#include <vector>
using namespace std;
class Custom {
public:
int v;
Custom() = delete;
explicit Custom(int v) : v{v} {};
Custom(const Custom &) : v{4} {
}
friend ostream &operator<<(ostream &os, const Custom &th) {
os << "V is " << th.v << endl;
return os;
}
};
int main(int argc, char *argv[]) {
vector<Custom> c(2, Custom(3));
c[0].v = 5;
for (auto i: c) {
cout << i << endl;
}
}
I expected it to produce the output
V is 5
V is 4
But instead it produces
V is 4
V is 4
Am I missing something obvious? Thanks.
This range based loop is making copies:
for (auto i: c) {
cout << i << endl;
}
And the copy constructor initializes v to 4 (and does not make a copy):
Custom(const Custom &) : v{4} {
}
You can either implement a proper copy constructor or use references in the loop to get the desired output:
for (const auto& i: c) {
cout << i << endl;
}
I would suggest to do both, because this copy constructor is not doing a copy by any means. The compiler generated copy constructor should be fine:
Custom(const Custom &) = default;
PS: The fact that Custom has a deleted default constructor is not really relevant for the posted code. Nowhere in the code a Custom is default constructed. Also there is no iterator in your code. In the range based loop i is a copy/reference of the elements in the vector, it is not an iterator.
When you wrote:
for (auto i: c) //this uses copy constructor to copy initialize each element one by one from the vector
{
}
In the above snippet, each individual element of the vector is used to copy initiaize a temporary object named i while iterating through the vector. And since you have the v{4} in the constructor initializer list of the copy constructor you get the mentioned output.
To solve this you should replace: auto i: c with auto &i: c or const auto &i: c as shown below:
for (const auto &i: c)
{
cout << i << endl;
}
Now the elements of the vector are not copied into i. Instead they are references to the object themselves and so you'll get your expected output.

What is the meaning of bool operator () (int num)?

Is () used in the bool operator()(int num) of the below code a another operator or it means something else ? Please help.
#include <iostream>
#include <vector>
#include<algorithm>
using namespace std;
class IsOdd{
public:
bool operator()(int num){
return ((num%2)==1);
}
};
int main(){
vector <int> v {1,2,3,4,5,6,7,8,9,10};
vector <int>::iterator pend;
vector<int>:: iterator q;
pend = remove_if(v.begin(), v.end(), IsOdd());
for(q=v.begin(); q!=pend;++q)
cout<<*q<<endl;
return 0;
}
That means overloading the operator () to work with the IsOdd class.
Here is a sample of code of the overloaded operator in action:
#include <iostream>
#include <vector>
#include<algorithm>
class IsOdd {
public:
bool operator()(int num) {
return ((num % 2) == 1);
}
};
int main()
{
std::vector <int> v{ 1,2,3,4,5,6,7,8,9,10 };
IsOdd isOdd; // Defining object isOdd of the class IsOdd
for (int i = 0; i < v.size(); i++)
{
if (isOdd(v[i])) std::cout << v[i] << " is odd." << std::endl;
else std::cout << v[i] << " is not odd." << std::endl;
}
return 0;
}
I've also removed the iterators and shown with a much simpler way to iterate through elements in a std::vector.
Also, you should not use the following in your code:
using namespace std;
...as it's considered as bad practice.
Output:
1 is odd.
2 is not odd.
3 is odd.
4 is not odd.
5 is odd.
6 is not odd.
7 is odd.
8 is not odd.
9 is odd.
10 is not odd.
It's a function, and the () is part of the name - operator() is a special spelling for "function that is used to make an object behave like a function".
(It's a bit strange to call it "operator", but the C++ committee prefers reusing keywords to introducing new ones.)
If you have an object of the IsOdd type, such as
IsOdd is_odd;
then what looks like a regular function call,
is_odd(3)
is transformed behind the scenes into
is_odd.operator() (3)
IsOdd is a functor class. It has an overload of the function call operator, so that given an instance x you can call it via x(42) to determine if 42 is odd.
In the code it is used to pass a callable to the algorithm. Nowadays you would rather use a lambda:
auto isOdd = [](int x) { return ((num % 2) == 1);};
pend = remove_if(v.begin(), v.end(), isOdd);
or perhaps, if the functor is only needed for the algorithm but not elsewhere, define the lambda in-line:
pend = remove_if(v.begin(), v.end(), [](int x){ return ((num % 2) == 1);});
Is () used in the bool operator()(int num) of the below code a another operator or it means something else ?
Here:
pend = remove_if(v.begin(), v.end(), IsOdd());
the () in IsOdd() is a call to the constructor to create an instance of the class IsOdd. The operator() of that instance is then called by the algorithm. If you like you could also call it yourself:
auto x = IsOdd(); // call constructor
std::cout << x(42); // call operator()
It means it's a function named operator(), returns a boolean, and takes in an integer named num.
Edit:
Its an overloaded function operator so you can have it take no arguments or the argument int num.

Is std::map creating a new non const copy of object from its const reference

Consider the following code .
#include <iostream>
#include <map>
class A{
public:
int m_id;
int m_x;
int m_y;
A() = default;
A(int i, int j, int k) : m_id(i), m_x(j), m_y(k){}
};
void add(const A& a, std::map<int,A>& m){
m[a.m_id] = a;
}
void modify(std::map<int,A>& m){
for(auto& x : m){
x.second.m_x*=10;
x.second.m_y/=10;
}
}
void print(std::map<int,A>& m){
for(const auto& x : m){
std::cout << x.first << " : (" << x.second.m_x << ',' << x.second.m_y << ")\n";
}
std::cout << '\n';
}
int main(int argc, char const *argv[])
{
std::map<int,A> m;
A a(1,10,100);
add(a,m);
print(m);
{
A b(2,10,200);
add(b,m);
print(m);
}
modify(m);
print(m);
return 0;
}
I am creating a std::map of objects of type A. In add, I add an object to the std::map by using a const reference to that object. In modify, I am modifying values of std::map. In print, I am printing the map. Basically accessing the elements.
I add b in a different scope to test if it I get a memory error.
The code works correctly.
My question is, is std::map with [] operator creating a new non const copy of the object ? Also, std::vector::push_back works fine. Does push_back also create a copy. I am not calling emplace.
Yes, a new object will be constructed as the element of std::map. To be precise, in m[a.m_id] = a;, if the key (i.e. a.m_id) does not already exist, a value-initialized A will be constructed as the new element of m firstly, then m[a.m_id] returns the reference to value of the new element; which is copy-assigned from a via the copy-assignment operator of A later.
If the key (i.e. a.m_id) already exists, m[a.m_id] just returns the reference to value of the existed element; which is copy-assigned from a then.

Why does 'for_each' not reading function object

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
template <class T>
class Sum {
public:
Sum(T i = 0) : res(i) {}
void operator()(T x) { res =res + x; }
T result() const { return res; }
private:
T res;
};
int main() {
Sum<int> s;
vector<int> vec;
vec.insert(vec.begin(), 10);
vec.insert(vec.begin()+1, 10);
vec.insert(vec.begin()+2, 10);
vector<int>::iterator itr = vec.begin();
cout << *itr << endl;
for_each(vec.begin(), vec.end(), s);
cout << "sum is" << s.result() << endl;
return 0;
}
This is my code. I want to add vec values in class Sum res. for_each should be calling s's operator(), so the result should be 30, but it shows 0.
I think adding value in vector has no problem. Why is the s.operator() is not working?
for_each takes its third argument by value which means every invocation of operator() affects a completely separate copy of s. There's an algorithm for exactly what you're doing called std::accumulate, but if you want this to work with for_each you need to pass s "by reference" by using std::ref from <functional>.
for_each(vec.begin(), vec.end(), ref(s));
for_each returns a copy of the passed-in functor that provides the "result" of the iteration (whatever the result is). Change your call to:
auto s = for_each(vec.begin(), vec.end(), Sum<int>());

function objects and constructors

I was just reading this
class biggerThan
{
public:
const int testValue;
biggerThan(int x) : testValue(x) { }
bool operator()(int val) const
{ return val > testValue; }
};
Now say its used like
std::list<int>::iterator firstBig =
std::find_if(aList.begin(), aList.end(), biggerThan(12));
OR
Just simply like this
biggerThan object(12)
Now when biggerThan(12) this is used it can invoke the constrcutor to initialze the testvalue or () operator is overloaded and 12 is passed to the function(bool operator()(int val) const ) so that it returns a bool.
which one happens first/how does it works
does it leads to any ambiguity or does the call to the overlaode operator happens in some fashion like
object.operator().(12).
please make my undersatnding clear.
Maybe the following code will make it clear:
#include <iostream>
#include <algorithm>
class biggerThan
{
public:
const int testValue;
biggerThan(int x) : testValue(x) {
std::cout << "Construction of biggerThan object with value "
<< x << std::endl;
}
bool operator()(int val) const
{
if (val > testValue) {
std::cout << val << " is bigger than " << testValue
<< std::endl;
return true;
}
else {
std::cout << val << " is *not* bigger than " << testValue
<< std::endl;
return false;
}
}
};
int main() {
int data[] = {0,1,2,3,4,5,6,7,8,9};
std::for_each(data, data+10, biggerThan(4));
}
The output is:
Construction of biggerThan object with value 4
0 is *not* bigger than 4
1 is *not* bigger than 4
2 is *not* bigger than 4
3 is *not* bigger than 4
4 is *not* bigger than 4
5 is bigger than 4
6 is bigger than 4
7 is bigger than 4
8 is bigger than 4
9 is bigger than 4
What happens:
The last argument to std::for_each is an object of type biggerThan, that is constructed with the argument 4.
The operator()(int) of this biggerThan-object (actually a copy of it) is invoked for every element in data.
The algorithm you use (std::find_if) works the same in this regard.
when biggerThan(12) this is used it can invoke the constructor to initialize the testvalue
Yes. biggerThan(12) creates an instance of the biggerThan class with testvalue set to 12.
When std::find_if() calls the functor, it will call the operator()(int val) member function of that instance.
biggerThan(12) will pass an object of biggerThan at std::find_if(aList.begin(), aList.end(), biggerThan(12)); line;
To invoke operator() following is the way;
biggerThan obj(12); //This is a constructor call
biggerThan(13); //This is function operator call
#std::find_if(aList.begin(), aList.end(), biggerThan(12)); the third parameter that is passed will be temporary object of biggerThan initialized with 12
In general, you can accomplish the same thing using greater<> and bind2nd<>, which are in <functional>
list<int>::iterator firstBig = find_if(aList.begin(), aList.end,
bind2nd(greater<int>(), 12));
bind2nd turns any binary function object, like greater<int> into a unary function object. In the case of greater<int> it effectively creates a function object whose less than operator looks like this
bool operator>(const int& arg)
{
return functor.operator>(arg, 12);
}
where functor is greater<int>