I was revisiting the concepts of structures in C++ before the lectures and written the following:
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
struct isOdd{
bool operator()(int x){
return x%2;
}
};
int main(){
vector<int> v {3,4,2,1,65,2,4,65,2,9,8,5,7};
int count = count_if(begin(v), end(v), isOdd());
cout << "size of vector: " <<v.size() << endl;
cout << "count of odds: " <<count << endl;
return 0;
}
Then I realize that in calling function of structure isOdd, I have used the syntax: isOdd() but I have only overridden the () operator. So how the calling convention isOdd() is working because the calling a function of structure is like:
structure::function-name();
or structure-object.functions-name();
Can somebody elaborate the doubt?
Thanks.
Then I realize that in calling function of structure isOdd, I have
used the syntax: isOdd() but I have only overridden the () operator.
No, You called the implicit compiler generated default constructor, thereby creating a temporary object of isOdd.
For example: If you wanted to test it on a single number without creating a named isOdd object, you could:
bool is_odd = isOdd()(4);
//^^ Creates a temporary object
Optimizing Compilers will elide the creation of the temporary object since it neither has observable side effects nor a state.
Related
I am new to C++ and get confused about what goes on under the hood when a class method returns a reference to a member variable that is raw data (rather than a pointer or a reference). Here's an example:
#include <iostream>
using namespace std;
struct Dog {
int age;
};
class Wrapper {
public:
Dog myDog;
Dog& operator*() { return myDog; }
Dog* operator->() { return &myDog; }
};
int main() {
auto w = Wrapper();
// Method 1
w.myDog.age = 1;
cout << w.myDog.age << "\n";
// Method 2
(*w).age = 2;
cout << w.myDog.age << "\n";
// Method 3
w->age = 3;
cout << w.myDog.age << "\n";
}
My question is: what happens at runtime when the code reads (*w) or w-> (as in the main function)? Does it compute the address of the myDog field every time it sees (*it) or it->? Is there overhead to either of these two access methods compared to accessing myDog_ directly?
Thanks!
Technically, what you are asking is entirely system/compiler-specific. As a practicable matter, a pointer and a reference are identical in implementation.
No rational compiler is going to treat
(*x).y
and
x->y
differently. Under the covers both usually appears in assembly language as something like
y(Rn)
Where Rn is a register holding the address of x and y is the offset of y into the structure.
The problem is that C++ is built upon C which in turn is the most f*&*) *p programming language ever devised. The reference construct is a work around to C's inept method of passing parameters.
Here's an extremely basic example of my question.
#include <iostream>
#include <string>
using namespace std;
int x;
void test(int x) {
x += 3;
cout << x << endl;
}
int main() {
test(x);
cout << x << endl;
return 0;
}
the output is:
"3" (new line) "0"
How can I specify inside of the "test()" function that I want the class's 'x' variable to have the 3 added to it instead of the temp variable inside of the function?
In java you specify that you're dealing with the function/method's variable by using '"this". Is there a similar way to do this in C++?
In your case you can use :: to specify to use global variable,
instead of local one:
void test(int x) {
::x += 3;
cout << ::x << endl;
}
And it is not class member or so on just global and local.
In the C++ language, create a class or struct and you can use this->x the same as this.x in the Java language.
First of all, thank you for stating that you come from Java. This will help us a lot in terms of helping you!
Now, let's analyze your code
#include <iostream>
#include <string>
using namespace std;
Including some headers, using the std namespace (not recommended, BTW), everything's okay here.
int x;
You declare a variable named x of type int at global scope, with an initial value of zero (this only applies to objects at global scope!).
void test(int x) {
x += 3;
cout << x << endl;
}
You declare a function test that takes a parameter x of type int and returns void (a.k.a: nothing). The function increments the value of its intenral x variable by 3, then prints that to standard output by means of std::cout. Just to be clear, once you declare the int x parameter, it "hides" the int x at global scope, thus if you want to access the later, you have to use another way (see below).
int main() {
test(x);
cout << x << endl;
return 0;
}
You declare the special main function, taking no parameters and returning int. The function calls test with the global int x as argument, then prints the value of the global x to the standard output by means of std::cout, and finally returns zero, indicating successful execution.
Now, you have a big misconception, that you can attribute to the single-paradigm design of the Java language. In Java, there's no concept of "global functions", not to even say there are no "functions" at all. You only have "classes" with "methods".
In C++, this is not the case. The C++ language is a multi-paradigm one; it allows you to do imperative programming, structured programming, object-oriented programming, and even functional programming (you're not expected to have understood that last sentence completely)! When you declare anything without specifying an scope, it's said to lie in the global scope. The global scope can be accessed by anything, anywhere. In the example you presented there are no classes involved!
In the global scope, something like void test(int) is not a method, but a function. There's no class "owning" that function; let's say it's of "everyone" ;). A function is just a block of code that you can reuse by giving it arguments, if the function has them at all. In C++, you use classes to encapsulate data and corresponding code in a single "packed" black-box entity, not for, well, anything, like in Java.
Now, (this is somewhat like Java, but be careful!), when you pass a "plain" object, such as an int or something more funky and complex like std:: (you were not expected to understand that...) to a function, that function gets a copy of that object. The int x in test is not the same as the one main passed to it. If you assign to it inside test, you'll notice main "sees no difference". In Java, this applies too, but only to the fundamental types like int, but in C++ it does for all types.
If you want to be able to change the variable you got, just use references. You get a reference of any type T by typing T&. So, if you assign to a int& x inside the now modified test, main will "see" all changes.
Finally, there's the :: operator. It's used to access stuff in some scope from, well, other scopes. It has the form namespace-or-class::stuff. So for example, std::cout refers to identifier cout in namespace std. There's a special case: if the left operand is not given, :: accesses the global scope. This is useful whenever you "hide" something from the global scope. So, for example, in test, you could say ::x, and that would refer to the x in the global scope!
void test(int x) {
// ...
::x += 123;
}
Edit: If you're curious, you can take a glance at how classes in C++ work with this (I won't explain it, because that's off-topic)...
#include <iostream>
int x = 0;
class MyClass {
private:
int x;
public:
MyClass() : x(0) {}
void test(int x) {
this->report(x);
std::cout << "Doing some magic...\n";
this->x += x;
this->report(x);
}
void report(int x) {
std::cout << "this->x = " << this->x << '\n';
std::cout << "x = " << x << '\n';
}
};
int main() {
MyClass c;
c.report();
x += 123;
c.test(x);
x += 456;
c.test(x);
c.report();
}
I have inherited my class from std::vector. Now I want to overload the []-operator.
When I try to assign a new value to my vector, e.g. v[0]=5, I should receive the message OK.
This is my code (I know, that makes no sense, I'm just playing around):
#include<vector>
#include<iostream>
class Vec : public std::vector<int> {
public:
int operator[](int);
};
int Vec::operator[](int i) {
(*this)[i] = i;
std::cout << "OK";
return 123;
}
int main() {
Vec v;
v[0]=5;
}
Unfortunately I get the following error:
In member function ‘int Vec::operator[](int)’:
error: lvalue required as left operand of assignmen
In function ‘int main()’:
error: lvalue required as left operand of assignment
This particular error is caused because you are not returning an lvalue, generally defined as something that can appear to the left of an assignment, such as v[0] = 5;. You have more problems as pointed out in the other answers but this is the specific issue you face with that error message (a).
The correct specification for overloading the index operator is:
int& operator[] (const int nIndex);
You have to return a reference to the item (so it can be modified) if you want to treat it as an lvalue. The following code shows a fix, although obviously all array indexes map to the same value in this simplified case:
#include <vector>
#include <iostream>
class Vec : public std::vector<int> {
public:
int& operator[] (int); // <-- note the '&'
private:
int xyzzy;
};
int& Vec::operator[] (int idx) { // <-- note the '&'
std::cout << "OK\n";
return xyzzy;
}
int main () {
Vec v;
v[0] = 5;
v[1] = 6;
std::cout << v[22] << '\n';
return 0;
}
The output of this is:
OK
OK
OK
6
In reality, you wouldn't map all indexes to the same value, the code above is simply to illustrate the correct function signature. I haven't bothered to give a more complete example since subclassing classes with non-virtual destructors regularly leads to problems in non-trivial code (b).
(a) It's not usually considered a good idea to subclass std::vector since the destructor isn't virtual, so you can get into trouble when trying to destroy an object polymorphically.
You're probably better off using a has-a relationship (where your class contains a vector) rather than an is-a relationship (where you inherit).
That unfortunately means you may have to create a lot of pass-through methods from your class to the underlying vector (although only the ones you need) but it will solve the problem with the destructor.
(b) See (a) :-)
You'd need to return a reference to your element - however note that even if you did, you'd run into inifinite recursion - your operator[] calls itself.
Either way - inheriting from std::vector isn't a good idea. Use composition instead.
The code below illustrates how to call the operator[] from the vector base class....
#include <iostream>
#include <vector>
struct Vec : std::vector<int>
{
int& operator[](int n)
{
std::cout << "operator[](" << n << ")\n";
return std::vector<int>::operator[](n);
}
};
int main()
{
Vec v;
v.push_back(10);
v.push_back(20);
v[0] += 5;
std::cout << v[0] << ' ' << v[1] << '\n';
}
Output when I run it:
operator[](0)
operator[](1)
operator[](0)
15 20
Don't take all this talk about "do not inherit from std::vector" too seriously: you have to go out of your way to delete a dynamically allocated Vec using a std::vector<int>*, or do an accidental by-value slicing copy - and even then it'd probably only bite you if you had added data members. You should make sure you understand those risks then make your own assessment, but for small utility programs etc. it's productive to inherit from such classes sometimes....
I am trying to call the constructor H, but for some reason its not being called.
I get no error when I compile my code, and I get the output:
A object initialized.
H object initialized.
If H was initialized properly, the cout from the constructor should also be shown.
Can someone please help? Thank you.
I also have another question. How can I change the value of hVec[i].a and have the value of
aArray[i].a take upon this value as well? I know I am suppose to use pointers, but an very confused. Sorry for all the questions; I'm reltaively new to programming in C++.
#include <vector>
#include <iostream>
struct A
{
A(int av):a(av){}
int a;
};
struct Heap
{
Heap(std::vector<A> hVal)
{
std::cout << "Constructor for H object. \n";
for (int i=0; i<hVal.size(); ++i)
{
hVec.push_back(hVal[i]);
std::cout << "hVec[i].a = " << hVec[i].a << " ";
}
std::cout << std::endl;
}
std::vector<A> hVec;
};
int main()
{
A a0(2), a1(4), a2(8);
std::vector<A> aArray;
aArray.push_back(a0);
aArray.push_back(a1);
aArray.push_back(a2);
std::cout << "A object initialized. \n";
Heap h(A);
std::cout << "H object initialized. \n";
return 0;
}
Your struct Heap does not have a constructor which takes A as argument.
However, you can initialize h with aArray which is std::vector<A> type
Heap h(aArray);
In C++, unless you are trying to be compatible with C, otherwise just use class instead of struct
Heap h(A);
This declares a function of type Heap(A) named h. Perhaps you meant:
Heap h(aArray);
This declares a local variable of type Heap named h.
use Heap h(aArray); instead of Heap h(A);
The line Heap h(A); declares a function h taking an object of type A as parameter, and returns an object Heap.
I am a C programmer,
Now I am picking up C++ concepts (together with boost library).
please have look at my program and its output:
#include <boost/thread.hpp>
#include <iostream>
using namespace std;
class PowerClass
{
private:
int m, n;
public:
double *result;
PowerClass(int m, int n)
{
cout<<"I am in constructor " << this << endl;
this->m=m; this->n=n;
result = new double;
}
void operator () ()
{
cout<<"I am in () " << this << endl;
*result=m;
for (int i=1; i<n; ++i)
{
*result*=m;
boost::this_thread::yield();
}
}
};
int main()
{
PowerClass p(2,3);
cout<<"class created " <<&p<<endl;
boost::thread t(p);
t.join();
}
the out put is:
I am in constructor 0xbfcfe40c
class created 0xbfcfe40c
I am in () 0x9d0f154
The question could be more silly than plain:
I know () operator overloading function will be called upon thread creation, but why do I get a different address for the object (this) in the () operator, than the address of the same object in main() and constructor?
is this another copy of the object? why? how may I get work on the same object in () operator overloading function.
Thank you
You are passing the function parameter(which is your object) by value hence your overloaded function receives a copy of the object.
Of-course, the objects are places at different memory addresses and hence the different address.
You will need to pass the object by Reference to receive the same object inside your function.
Youre passing by value, instead of by reference, so the object is copied. hence the different address.
Add the following:
PowerClass(PowerClass const& copy)
: m(copy.m)
, n(copy.n)
, result(new double(*copy.result))
{
cout<<"I am COPY constructor " << this << " FROM: " << © << endl;
}
This will let you see the copy being made.
PS. You are leaking memory.
Edit: From comments below
I am in constructor 0xbf95cc30 class created 0xbf95cc30
I am COPY constructor 0xbf95cc3c FROM: 0xbf95cc30
I am COPY constructor 0xbf95cc04 FROM: 0xbf95cc3c
I am COPY constructor 0xbf95cb94 FROM: 0xbf95cc04
I am COPY constructor 0x941b184 FROM: 0xbf95cb94
I am in () 0x941b184
Question:
I notice that the I will finally have 2 copies(two object) ok. Any way, why do I get 4 messages of calls to the () overload function?
You don't you get 4 calls to the copy constructor (so there are actually 5 instances of the object around the program). Your object is being copy around inside thread most probably. If you add a print statement to the destructor you will see when they are being destroyed.
This usually happens when you don't have optimized tuned on (the optimizer can eliminate a lot of the default copying).
If you are using g++ then add -O3 If you are using MS tools build in release mode.