I have a list of derived class objects of 3 types, each contains string and two integers.
#include "pch.h"
#include <iostream>
#include <list>
#include <string>
#include <algorithm>
#include <iterator>
class Shape
{
private:
int x, y;
public:
Shape() {}
Shape(int &x_, int &y_) : x(x_), y(y_) {}
virtual void Draw() {
std::cout << this->x << ", " << this->y << "}\n";
}
};
class Circle : public Shape
{
private:
std::string type;
public:
Circle() {}
Circle(int &x_, int &y_) : Shape(x_, y_) { this->type = "Circle"; }
void Draw() {
std::cout << this->type << ": {";
Shape::Draw();
}
};
class Triangle : public Shape
{
private:
std::string type;
public:
Triangle() {}
Triangle(int &x_, int &y_) : Shape(x_, y_) { this->type = "Triangle"; }
void Draw() {
std::cout << this->type << ": {";
Shape::Draw();
}
};
class Square : public Shape
{
private:
std::string type;
public:
Square() {}
Square(int &x_, int &y_) : Shape(x_, y_) { this->type = "Square"; }
void Draw() {
std::cout << this->type << ": {";
Shape::Draw();
}
};
void FillWithShapes(int n, std::list<Shape*> &ls) {
int x, y, type;
Circle cir;
Triangle tri;
Square sq;
for (int i = 0; i < 10; i++) {
type = rand() % 3;
x = rand() % 100;
y = rand() % 100;
if (type == 0) {
cir = Circle(x, y);
ls.push_back(&cir);
}
else if (type == 1) {
tri = Triangle(x, y);
ls.push_back(&tri);
}
else if (type == 2) {
sq = Square(x, y);
ls.push_back(&sq);
}
}
}
int main()
{
std::list<Shape*> shapes;
FillWithShapes(10, shapes);
std::for_each(shapes.begin(), shapes.end(), [](Shape *s) { s->Draw(); });
}
I'm getting read access violation exception when accessing list elements in lambda:
Exception thrown: read access violation.
s->**** was 0xCCCCCCCC.
But when I put the code from function FillWithShapes
straight to main()
, it works just fine:
Square: {18, 95}
Triangle: {82, 21}
Circle: {2, 53}
Square: {18, 95}
Triangle: {82, 21}
Square: {18, 95}
Circle: {2, 53}
Circle: {2, 53}
Triangle: {82, 21}
Square: {18, 95}
I have started learning c++ not long ago, so I have no idea what may cause this exception in this case, though I'm probably missing something simple but significant here.
UPD: Fixed function to create pointers on heap:
void FillWithShapes(int n, std::list<Shape*> &ls) {
int x, y, type;
Circle *cir = new Circle();
Triangle *tri = new Triangle();
Square *sq = new Square();
for (int i = 0; i < 10; i++) {
type = rand() % 3;
x = rand() % 100;
y = rand() % 100;
if (type == 0) {
*cir = Circle(x, y);
ls.push_back(cir);
}
else if (type == 1) {
*tri = Triangle(x, y);
ls.push_back(tri);
}
else if (type == 2) {
*sq = Square(x, y);
ls.push_back(sq);
}
}
}
In your function FillWithShapes
, you are creating objects of type Circle
, Sqaure
etc and pushing those pointers into the vector. Once that function goes out of scope, these pointers are no longer valid.
You could create the objects on the heap and push those in the vector
with the burden of de-allocating once done with the vector.