Can't assign array element to class variable while overloading "=" operator - c++

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.

Related

Values of objects in vector reset when trying to get the value, although it was incremented

So as you can see down below, I try increment the x value of the bird by 1. But the value gets reset every time I call the getX() function.
#include <iostream>
#include <vector>
class Bird {
public:
Bird(double inputX, double inputY) : x(inputX), y(inputY) {
}
void tick() {
x++;
}
double getX() {
return x;
}
double getY() {
return y;
}
private:
double x, y;
};
class Test {
public:
void addToVector(double x, double y) {
Bird bird(x, y);
birds.push_back(bird);
}
std::vector<Bird> getVector() {
return birds;
}
private:
std::vector<Bird> birds;
};
int main(int argc, char* agrs[]) {
Test test;
for (int i = 0; i < 5; i++) {
test.addToVector(0, 0);
}
for (int i = 0; i < test.getVector().size(); i++) {
std::cout << "Index: " << i << " x: " << test.getVector()[i].getX() << " y: " << test.getVector()[i].getY() << std::endl;
}
while (true) {
for (int i = 0; i < test.getVector().size(); i++) {
test.getVector()[i].tick();
}
for (int i = 0; i < test.getVector().size(); i++) {
std::cout << "Index: " << i << " x: " << test.getVector()[i].getX() << " y: " << test.getVector()[i].getY() << std::endl;
}
}
}
So I know, that the problem is that I create the bird in the function and "copy" it to the vector. But the bird goes out of scope so I get a memory leak. I tried using unique pointers, but I couldn't declare the bird with a name because of that. I also don't know how to prevent that the destruction of the bird
So I know, that the problem is that I create the bird in the function and "copy" it to the vector
No. That's not a big problem. You could create the bird directly in the vector rather than first creating one then then copy it in the vector. Though, making the copy is not the reason for the output you get, its just a copy that could be avoided.
But the bird goes out of scope so I get a memory leak.
No. There is also no memory leak in your code.
I tried using unique pointers, ...
Hm, ok. Not sure what you did, or what was the problem with that code. Anyhow, the actual problem is...
Your getVector returns a copy of the member. Modifying that copy has no effect on the member. The easy fix to get expected output is to change the getter to return a reference:
std::vector<Bird>& getVector() {
return birds;
}
However, now the question arises why birds is private in the first place. Once you return a non-const referene to the outside of the class the caller can use this reference to do what they like, just as if the member was public.
Rather than designing your classes as data containers with getters and setters to set and get their members you should design the classes according to their behavior (unless the aim is to implement a plain data container of course). Here, rather than returning the whole vector to the caller you could let the caller specify which bird they want to tick and provide a mehtod to print contents of the vector. Something along the line of (not tested, and not changing Bird other than removing one member):
class Bird {
public:
Bird(double inputX) : x(inputX) {}
void tick() { x++; }
double getX() const { return x; } // should (/must) be const !
private:
double x;
};
class Birdies {
public:
void addToVector(double x) {
birds.push_back(x); // still creates a tempory that is copied, look at emplace_back
}
void makeTick(size_t index) {
birds[index].tick();
}
void print() const {
for (const auto& b : birds) std::cout << b.getX() << "\n";
}
private:
std::vector<Bird> birds;
};
No, you are misunderstanding the problem, it has nothing to do with the destruction of any bird object.
The problem is here
std::vector<Bird> getVector() {
return birds;
}
This function returns a copy of the vector in the Test object. So when you call tick you are modifying a copy of the vector not the original.
Change to this to return a reference to the vector, not a copy
std::vector<Bird>& getVector() {
return birds;
}

C++ Polymorphism: How to write function to accept any abstract class implementation

I want to be able to pass whatever implementation of an abstract class into a function defined in a separate file, so that I can use the functionality for other projects and write the child class however it suits me.
main.cpp:
#include "my_process.h"
struct my_guy : V2 {
my_guy(float x, float y)
: V2(x, y) { }
void double_me() override {
x *= 2.f;
y *= 2.f;
}
};
int main() {
process(my_guy(1.f,2.f));
return 0;
}
my_process.h:
#pragma once
#include <iostream>
struct V2 {
float x, y;
V2(float x, float y) {
this->x = x;
this->y = y;
}
virtual void double_me() { }
};
std::ostream& operator<<(std::ostream& output_stream, V2 vector) {
output_stream << vector.x << ", " << vector.y;
return output_stream;
}
void process(V2 vector) {
vector.double_me();
std::cout << vector << std::endl;
}
The above example prints 1,2 instead of the expected 2,4
Your function process currently passes is parameter by value.
Because you currently pass by value, a new V2 value is created as the parameter, which will always have type V2 and act like a V2.
Change it to take a reference to whatever object is passed to it:
void process(V2 & vector)
Since the parameter is also modified, you will need to pass a named variable to convince the C++ compiler that you aren't accidentally modifying a temporary.
int main() {
auto guy = my_guy(1.f,2.f);
process(guy);
}

'this' pointer behaviour in c++

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.

Is it possible to use deferenced pointers in initalization list

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

How to delete instance class inside class

Consider this code snippet:
#include <iostream>
using namespace std;
class X {
public:
class Z {
public:
void f() {
cout << "Z().f()" << endl;
}
};
class Y {
public:
int A;
Y(int x) {
A = x;
}
int c() {
return A;
}
};
public:
Z* z;
// How to free Y instance ?
Y* a(int x) {
Y* y = new Y(x);
return y;
}
public:
X() {
z = new Z();
}
~X() {
delete z;
}
};
int main(void) {
int a;
X* x = new X();
cout << "input :" << endl;
cin >> a;
cout << "result : " << x->a(a)->c() << endl;
x->z->f();
delete x;
return 0;
}
While Z object can easily be freed on ~X(), i am curious how to free Y one ? Since i am not assigning any variable to hold its memory address.
Btw, what's the terminology for something like this ? x->a(a)->c()
Thank you. :)
// How to free Y instance ?
Y* a(int x) {
Y* y = new Y(x);
return y;
}
Well, the problem is that it is not clear from the function prototype who is responsible for deleting the instance. But since only the caller has a handle to the instance, then it should be the called's responsibility to delete. This should be well documented. But the best approach would be to use a smart pointer with the right ownership semantics. In this case, std::unique_ptr<Y> seems like an appropriate match, and the mere fact of using it makes the intent clear, removing the need for documentation concerning ownership:
std::unique_ptr<Y> a(int x)
{
return std::unique_ptr<Y>( new Y(x) );
}
You're returning the memory from the function, so it is up to the caller to delete it:
X x;
Y *ptr = x.a(5);
delete ptr;
Hopefully you never have to do something like this. If you must then it's recommended that you use smart pointers like a shared_ptr or unique_ptr.
std::unique_ptr<Y> a(int x) {
return std::unique_ptr<Y>(new Y(x));
}
With this, you never have to worry about deleting the instance as the destructor of the pointer class holds that responsibility.