I'm trying to get my head around pointers/destruction and such. I'm using the code below to use pointer for x instead of a standard int; however if I use an initialization list in the constructor it won't compile, while if I just assign it normally in the constructor method it's works fine.
#include<iostream>
using namespace std;
class Point
{
private:
int *x;
int y;
public:
Point(int x1, int y1):*x(x1),y(y1) {}
// Copy constructor
Point(const Point &p2) {*x = *p2.x; y = p2.y; }
// ~Point(){delete x;}
int getX() { return *x; }
int getY() { return y; }
void setX(int x1){*x=x1;}
};
int main()
{
Point p1(10, 15); // Normal constructor is called here
Point p2 = p1; // Copy constructor is called here
p2.setX(35);
// Let us access values assigned by constructors
cout << "p1.x = " << p1.getX() << ", p1.y = " << p1.getY();
cout << "\np2.x = " << p2.getX() << ", p2.y = " << p2.getY();
return 0;
}
I also have a second question, which is the correct way to initize a int pointer like this:
int *p = new int;
*p = 3;
or like this:
int *p;
*p = 3;
I noticed if I assign nullptr or 0 and try to display the pointer it doesn't output anything is there a reason for this? eg:
int *p = 0;
*p = 3;
cout << *p;
Point(int x1, int y1):*x(x1),y(y1) {} is not allowed syntax. You can only initialize members in the initialization lists, and *x is not a member. Btw, even if the compiler would allow it, it would produce undefined behaviour - you would be dereferencing an un-initialized pointer.
One way (at least, syntaxically correct and not leading to undefined behaviour in this very line) would be
Point(int x1, int y1): x(new int(x1)), y(y1) {}
The second question actually is the same as the first. In the second example, you would be accessing the pointer without initializing it first, which would end up in undefined behaviour.
When the constructor is called Point(int x1, int y1):*x(x1) , your x adress is not correct (not assigned), because it was not initialized so it can point anywhere in your RAM.
When you do *x(x1), if it is allowed, you will:
either corrupt your current memory
either segfault
Related
I am quite new in C++ programming, so maybe that's why I can't figure out why this assignment is not working.
In my class, I want to overload "=" operator.
I have specified a function, that outputs variables as an array. In overloading, I want to assign those variables to new object.
obj_new = obj_with_variables
overloading:
obj_new_x=obj_with_values_parameters()[0];
obj_new_y=obj_with_values_parameters()[1];
Here is a code:
// Test1.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
#include "string"
using namespace std;
class Vector2D
{
public:
Vector2D()
{
}
Vector2D(int& a, int& b)
:x(a), y(b)
{
}
void Drukuj()
{
cout << "wektor [" << x << ',' << y << "] \n";
}
void Wspolrzedne(int&a, int&b)
{
x = a;
y = b;
}
int* Wspolrzedne()
{
int tab[2] = { x,y };
return tab;
}
void operator = (Vector2D& obj)
{
int* a = obj.Wspolrzedne();
cout << a[0] << "\n";
x = a[0];
cout << x << " what? \n";
y = a[1];
}
private:
int x, y;
};
int main()
{
int x1 = 2, x2 = 3;
Vector2D wektor(x1, x2);
wektor.Drukuj();
Vector2D wektor2;
wektor2 = wektor;
wektor2.Drukuj();
wektor.Drukuj();
return 0;
}
The problem is that it assigns some strange values. However, if I don't use a reference, but declare 2 int values (j,k) and assign array element to them [0,1], it works fine.
Also, when using static numbers (for example, instead of a[0] ; use "2") it works fine too.
What is going on?
I would be glad if somebody could point me to right answer/ resources.
Regards,
In your member function int* Wspolrzedne(), you return the address of local variable tab. Accessing this variable once its life time has ended, as you do in your = operator, is undefined behaviour.
Your code has undefined behavior because operator= is accessing invalid data. Wspolrzedne() is returning a pointer to a local variable tab that goes out of scope when Wspolrzedne() exits, thus the a pointer used in operator= is not pointing at valid data.
If you want Wspolrzedne() to return multiple values, you need to have it return (by value) an instance of a struct or class to hold them. Try something more like this:
#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;
struct Coordinate {
int x;
int y;
};
class Vector2D
{
public:
Vector2D()
: x(0), y(0)
{
}
Vector2D(int a, int b)
: x(a), y(b)
{
}
Vector2D(const Coordinate &c)
: x(c.x), y(c.y)
{
}
Vector2D(const Vector2D &src)
: x(src.x), y(src.y)
{
}
void Drukuj()
{
cout << "wektor [" << x << ',' << y << "] \n";
}
void Wspolrzedne(int a, int b)
{
x = a;
y = b;
}
void Wspolrzedne(const Coordinate &c)
{
x = c.x;
y = c.y;
}
Coordinate Wspolrzedne()
{
Coordinate c = { x, y };
return c;
}
Vector2D& operator=(const Vector2D &obj)
{
Coordinate c = obj.Wspolrzedne();
cout << c.x << ',' << c.y << "\n";
Wspolrzedne(c);
return *this;
}
private:
int x;
int y;
};
On the other hand, there is no real reason to even have operator= call Wspolrzedne() to get the coordinates at all, when it can just access obj.x and obj.y directly instead:
Vector2D& operator=(const Vector2D &obj)
{
x = obj.x;
y = obj.y;
return *this;
}
In which case, you can simply eliminate your operator= altogether, and let the compiler provide a default-generated implementation that does the exact same thing for you.
Your interface is dangerous, as returning raw pointers from functions means the caller must know how to manage it. That is, the caller needs to be astutely aware of the answers to questions like, "should the caller delete the pointer or does the object I got it from retain ownership?" What is this pointer pointing to? If it's an array, now many elements are there? If I must delete it, do I use delete or delete[]?
And so on. This is not good because it's very, very error prone.
Next you have a function that returns a pointer to stack-local data. When the function returns, that memory is already invalid so the return value is always going to result in undefined behavior to read.
int* Wspolrzedne()
{
int tab[2] = { x,y };
return tab; // BAD - returns pointer to function stack data
}
Where does tab live? It's destroyed when the function exits, but you're returning a pointer to it.
This is a dangerous interface and should be changed. Perhaps you should return the values as a pair:
std::pair<int, int> Wspolrzedne()
{
return std::pair{ x,y }; // assuming c++17
// return std::pair<int, int>{x, y}; // older compilers
}
An interface like this avoids pointers, and removes all the issues mentioned above.
I have a basic understanding of this pointer in C++.While studying have come across the following code:
#include<iostream>
using namespace std;
class Test
{
private:
int x;
int y;
public:
//Test (int x = 0, int y = 0) { this->x = x; this->y = y; }
Test setX(int a) { x = a; return *this; }
Test setY(int b) { y = b; return *this; }
void print() { cout << "x = " << x << " y = " << y << endl; }
};
int main()
{
Test obj1;
obj1.setX(10).setY(20);
obj1.print();
return 0;
}
My issue is why the compiler deosn't report an error where I am returning a this pointer in SetX and SetY functions but haven't stated the return type as a pointer?
This comes because you're returning *this not this.
this is the pointer to a object of type Test. This means the this-variable basically holds the address where the object is stored. To access the object on which this points you use the *.
So you're returning the actual object on which you this Pointer points at.
EDIT
The problem why your code does not work in the way you want it to do is caused by the fact, that you're working on the stack.
Let's take a look at the addresses:
#include<iostream>
using namespace std;
class Test
{
private:
int x;
int y;
public:
//Test (int x = 0, int y = 0) { this->x = x; this->y = y; }
Test setX(int a) { x = a; return *this; }
Test setY(int b) {
y = b;
cout << this << endl; // >> 0x29ff18
return *this;
}
void print() { cout << "x = " << x << " y = " << y << endl; }
};
int main()
{
Test obj1;
cout << &obj1 << endl; // >> 0x29ff10
obj1 = obj1.setX(10).setY(20);
cout << &obj1 << endl; // >> 0x29ff10
//obj1.setY(20);
obj1.print();
return 0;
}
As you can see, the object where this points at is at a different address within you setY method compared to the main. This is because the object is copied to the stackframe of the setY method - so within setX and setY you're working with a copy of obj1
If you're doing obj1.setX(10).setY(20); you basically copy the object obj1 and use it within setX and the return object of setX is then used in setY. If you want to save the last copy, you have to reassign it to obj1.
Your solution to the problem works, but is grossly inefficient. The last paragraph describing what is happening is incorrect. setx is called with and uses obj1. sety is called with and uses copy of obj1. obj1 is then assigned copy of copy of obj1 returned by sety. The address doesn't change because obj1's storage is being overwritten, not replaced. Add a copy constructor and an assignment operator and you can watch what's really happening. The recommended solution is to use references to the same object throughout and chaining as per #πάνταῥεῖ 's answer below. – user4581301
My issue is why the compiler deosn't report an error where I am returning a this pointer in SetX and SetY functions but haven't stated the return type as a pointer?
It's completely valid syntax, so the compiler isn't supposed to return an error message. The problem is that you're using copies of this* with your return type.
To chain operations properly to operate on the original instance return a reference to this:
Test& setX(int a) { x = a; return *this; }
// ^
Test& setY(int b) { y = b; return *this; }
// ^
Otherwise you're returning an unrelated copy of your class.
What's the difference in usage of function get1() and get2()?
struct x
{
float get1() const
{
float fx = 4;
fx += 1.5f;
return fx;
}
float& get2() const
{
float fx = 4;
fx += 1.5f;
return fx;
}
};
int main()
{
x t;
float x1 = t.get1();
float/*&*/ x2 = t.get2();
cout << x1 << endl;
cout << x2 << endl;
cin.get();
}
As i understand, get2() can only be const class member..
It's not clear for me completely. If someone can point me to a reference or just a short but complete solution, would be nice.
In your case, get2() invokes undefined behavior because you return a reference to a method-local that goes out of scope.
The difference is that returning float returns a float value, while float & returns a reference to a float. The reference can be used to alter the data of the referent; when returning by value you just get a copy.
It sounds like you are just confused about what references do, so here is the colloquial definition: a reference is another name for an object. That means that a reference requires the existence of its target to exist elsewhere, very similar to a (non-null) pointer.
Let me write a better example to illustrate the difference:
struct x
{
x() : data(0) { }
float get1() const
{
return data;
}
// Cannot be const now, because we can't return a non-const reference to what
// would be a const data member. (If this method were const then data would be a
// const float, and that cannot bind to float &.)
float & get2()
{
return data;
}
private:
float data;
};
Now we have two methods, one that returns data and one that returns a reference to it. The difference here is that with get2() you can actually change the value of x::data:
x an_x;
float a = an_x.get1(); // a is 0
a = 5; // a is 5, an_x.data is still 0
a = x.get1(); // a is 0 again, because an_x.data did not change
float & b = an_x.get2(); // b is 0
b = 5; // b is 5, and so is an_x.data!
a = x.get1(); // a is now 5, because an_x.data is 5
Notably, returning a reference makes the result of the expression an lvalue:
an_x.get1() = 5; // Compile-time error, because a float is not an lvalue.
an_x.get2() = 5; // Compiles, and sets an_x.data to 5.
This is a technique used by the standard library containers; vector<int> for example returns int & from its non-const operator[] overload, which is why some_vector[0] = 5; compiles and works as you would expect.
float fx = 4;
In your case fx is local variable. It will die once you come out of function. If you are returning float then you are making copy of value, so even fx die, no problem. But if you are returning float&, you are returning reference to died variable. Which is undefined behaviour.
Copying is costly operation. When you return reference, you are not making actual copy, but you are returning address of varaiable. You should return reference if your variable will alive after returning from function. But in your case, fx will die once you come out of function.
I simulated your case in below blocks of code, you can compare the output of two case for making clearly. Hope it help.
#include <iostream>
class A
{
public:
A()
{
std::cout << this << ": A()\n";
}
A(const A&)
{
std::cout << this << ": Copy constructor\n";
}
~A()
{
std::cout << this << ": ~A()\n";
}
};
struct x
{
A get1() const
{
A a;
return a;
}
A &get2() const
{
A a;
return a;
}
};
int main(int argc, char *argv[])
{
x t;
/*{
t.get1();
}*/
{
t.get2();
}
std::cin.get();
}
I'm starting with developing, sorry about this newbie question.
I need to create a function that swap values between 2 vars.
I have wrote this code, but no changes are made in vars, What should I change? What is my mistake?
#include <iostream>
using namespace std;
void swap_values( int x, int y);
int main(void) {
int a,b;
a = 2;
b = 5;
cout << "Before: " << a << " " << b << endl;
swap_values( a,b );
cout << "After: " << a << " " << b << endl;
}
void swap_values( int x, int y ){
int z;
z = y;
y = x;
x = z;
}
You need to pass the variables by reference:
void swap_values( int& x, int& y )
{
int z;
z = y;
y = x;
x = z;
}
pass-by-value and pass-by-reference are key concepts in major programming languages. In C++, unless you specify by-reference, a pass-by-value occurs.
It basically means that it's not the original variables that are passed to the function, but copies.
That's why, outside the function, the variables remained the same - because inside the functions, only the copies were modified.
If you pass by reference (int& x, int& y), the function operates on the original variables.
You need to understand that by default, C++ use a call-by-value calling convention.
When you call swap_values, its stack frame receives a copy of the values passed to it as parameters. Thus, the parameters int x, int y are completely independent of the caller, and the variables int a, b.
Fortunately for you, C++ also support call-by-reference (see wikipedia, or a good programming language design textbook on that), which essentially means that the variables in your function are bound to (or, an alias of) the variables in the caller (this is a gross simplification).
The syntax for call-by-reference is:
void swap_values( int &x, int &y ){
// do your swap here
}
you are passing by value. you can still pass by value but need to work with pointers.
here is the correct code needed:
void swap(int *i, int *j) {
int t = *i;
*i = *j;
*j = t;
}
void main() {
int a = 23, b = 47;
printf("Before. a: %d, b: %d\n", a, b);
swap(&a, &b);
printf("After . a: %d, b: %d\n", a, b);
}
also a small document that explains "by reference" vs "by value" : http://www.tech-recipes.com/rx/1232/c-pointers-pass-by-value-pass-by-reference/
Just a tiny question:
Can you tell me what's the issue here in this code ? It should print out 9 but it does 4.8921e-270, however, when uncommenting line 4, it works just fine, too.
I don't understand what might be wrong here. Thank you !
Code:
double& foo() {
double x = 9;
double &y = x;
//cout << y << "\n";
return y;
}
int main() {
cout << foo() << "\n";
}
Result:
4.8921e-270
It is a bad idea to return references/pointers to objects on the stack. They are likely destroyed when you leave the function. Try returning it as per value:
double foo() {
double x = 9;
double &y = x;
//cout << y << "\n";
return y;
}
Now the return value is copied instead of a reference to an object that is probably not existing anymore.
You are returning a reference to a local object, the object ceases to exist when foo completes, and then you get Undefined Behavior when you dereference it.
double foo() {
double x = 9;
double &y = x;
//cout << y << "\n";
return y;
}
Never a good idea to return references to objects on stack. Most likely they would be disappear when you leave the function. You might try returning it as per value.
You return a reference to a local variable - since the local variable goes out of scope as soon as foo() returns, the value no longer exists.
So you should either just change the return type to double (highly recommended) and return x or (if you absolutely want/have to return a reference) use a static variable instead:
double& foo() {
static double x = 9;
double &y = x;
return y;
}
I often return data members of a class by const ref:
class BigThing {...};
class Foo
{
public:
const BigThing & getBT() const { return bt; } // For constant BigThing.
BigThing & getBT() { return bt; } // For mutable BigThing.
private:
BigThing bt;
};
Then as long as your instance of Foo is in scope (you don't want to return a ref to a local variable) then using one of the getBT() should be safe and efficient.