I have an object called Grid which is evolving in my main script. This is how I have defined Grid:
class Grid{
public:
std::vector <Polymer> PolymersInGrid; // all the polymers in the grid
std::vector <Particle> SolventInGrid; // solvent molecules in the grid
const int x; // length of x-edge of grid
const int y; // length of y-edge of grid
const int z; // length of z-edge of grid
const double kT; // energy factor
const double Emm ; // monomer-monomer interaction
const double Ess ; // solvent-solvent interaction
const double Ems_n ; // monomer-solvent when Not aligned
const double Ems_a ; // monomer-solvent when Aligned
double Energy;
std::map <std::vector <int>, Particle> OccupancyMap; // a map that gives the particle given the location
Grid(int xlen, int ylen, int zlen, double kT_, double Emm_, double Ess_, double Ems_n_, double Ems_a_): x (xlen), y (ylen), z (zlen), kT (kT_), Emm(Emm_), Ess (Ess_), Ems_n (Ems_n_), Ems_a (Ems_a_) { // Constructor of class
// this->instantiateOccupancyMap();
};
// Destructor of class
~Grid(){
};
...
};
In my main script, my Grid evolves when I apply an operator to Grid.
Grid G = CreateGridObject(positions, topology);
std::cout << "Energy of box is: " << G.Energy << std::endl;
for (int i{0}; i<NumberOfMoves; i++){
// perform evolution
Grid G_test (BackwardReptation(G, 0));
// check if G_test is a good structure
if (G_test is good){
// assign
G = G_test;
}
}
When I do this, I get the error
object of type 'Grid' cannot be assigned because its copy assignment operator is implicitly deleted. copy assignment operator of 'Grid' is implicitly deleted because field 'x' is of const-qualified type 'const int'.
I need to evolve Grid multiple times, check if it is good at each evolution step, and change its contents. How can I do this given that I want the geometry of Grid and the energy surface (Emm, Ess, Ems_n, Ems_a) are to be held const?
edit:
The following addition to my classobject worked:
Grid& operator=(const Grid& t){
return *this;
}
I understand that & is an overloaded operator, can be used to refer to addresses of variables, can be used for rvalues, lvalues. My question is, how does one read the syntax Grid& operator=? What does Grid& mean?
Related
I'm a high school student learning programming and I have a problem that I can't figure out how to solve.
I have an integer "x", and I want a matrix "mat" to have the size of "x":
int mat[x][x];
But that works only in main() where I've read x;
For example if x == 5, the equivalent would be
int mat[5][5];
#include <iostream>
using namespace std;
int x;
int mat[x][x];
void f(int mat2[x][x])
{
}
int main()
{
cin >> x;
int m[x][x];
f(m);
}
I've wrote this short program to show where it works and it doesn't work.
error: array bound is not an integer constant before ']' token
I've the error at the global declaration, at the declaration in function void f. It only compiles without errors in main();
What can I do to create a matrix with the size of x outside of the main function?
Variable length arrays aren't spported in standard c++. Besides you don't want the global definition.
What you can use portably in that case is std::vector:
void f(std::vector<std::vector<int>>& mat)
{
}
int main()
{
cin >> x;
std::vector<std::vector<int>> m(x,std::vector<int>(x));
f(m);
}
If you pass that vector around to functions or being allocated within functions, the size information will be kept at any time.
What can I do to create a matrix with the size of x outside of the main function?
Something like this:
std::vector<std::vector<int>> foo() {
cin >> x;
std::vector<std::vector<int>> m(x,std::vector<int>(x));
return m;
}
int main()
{
std::vector<std::vector<int>> mat = foo();
}
Handling of multi-dimension arrays in C++ is not easy. The best way to go is often to map a multi-dimensionnal indexing with a linear memory chunk.
For instance, for a 2 by 2 matrix, one can create an array of 2*2=4 elements and map it this way:
+-----------+-----------+-----------+-----------+
| map[0][0] | map[0][1] | map[1][0] | map[1][1] |
+-----------+-----------+-----------+-----------+
This seems overly complicated at first glance, but it simplifies greatly the memory allocation.
For an arbitrary sized matrix of width by height, map[i][j] is at index i*height + j. This can be translated in C++, encapsulated in a template class Matrix:
#include <array>
template <typename T, size_t WIDTH, size_t HEIGHT>
class Matrix {
std::array<T, WIDTH*HEIGHT> data;
public:
T& operator()(size_t i, size_t j) {
return data[i*HEIGHT + j];
}
const T& operator()(size_t i, size_t j) const {
return data[i*HEIGHT + j];
}
};
This has the disadvantage that the Matrix' dimensions must be known at compile time (and can be mitigated, see note (ii) at end of answer). But it makes its use so easy:
void fill(Matrix<int, 2, 2>& m) {
m(0,0) = 0;
m(0,1) = 1;
m(1,0) = 2;
m(1,1) = 3;
}
int main() {
Matrix<int, 2, 2> m;
fill(m);
std::cout << m(1,0) << "\n";
}
Note (i): Elements are indexed by (line, column) rather than [line][column] because we can't create an operator[] accepting multiple values.
Live on coliru
Note (ii): This basic idea can be enriched (demo) to handle resizable matrixes, with use of a std::vector instead of std::array and a proxy to std::vector::resize().
Variable-length array is supported by some compiler as an extension. The manual of the compiler provides more information.Gnu VLR
The storage duration of a variable-length array(if supported) generally can't be static, which is why you get the error message (global variables have static storage duration).
Unrelated: The major array bound of the parameter mat2 isn't necessary, i.e. void f(int mat2[x][x]) is equivalent to void f(int mat2[][x]).
C++ has no provision for dynamic 2D matrix but provides all you need to create complex classes. A (static) 2D array is a contiguously allocated array of height arrays of width elements. Just mimic that and:
allocate a linear array of width * height
provide an operator[](int) that returns a pointer to the first element of ith row
do necessary housekeeping in destructor and in a copy (and move if C++11 or above) constructor.
Example of code:
template <typename T>
class Matrix {
T *data;
int width;
int height;
public:
// direct ctor
Matrix(int h, int w): width(w), height(h) {
data = new T[w * h];
}
//copy ctor
Matrix(const Matrix& src): width(src.width), height(src.height) {
data = new T[width * height]; // allocate and copy data array
for (int i=0; i<width * height; i++) data[i] = src.data[i];
}
// move ctor
Matrix(Matrix&& src): width(src.width), height(src.height) {
data = src.data; // steal original array in a move
src.data = NULL; // ensure no deletion will occur at src destruction
}
~Matrix() {
delete data;
data = NULL;
}
// explicitely delete assignement operators
Matrix& operator = (const Matrix&) = delete;
Matrix& operator = (Matrix&&) = delete;
T* operator[](int i) {
//optionaly test 0 <= i < width
return &data[i * width];
}
};
int main()
{
int w;
std::cin >> x;
Matrix<int> m(x, x);
// you can then use m[i][j] as you would for a static 2D array
...
}
This class does not support any resizing by design. If you need that, you really should use a vector<vector<T> >. The downside is that it has no default ctor either, because the dimension must be given at definition time (even if we could easily imagine a 2 phases initialization...).
You can dynamic allocate memory to use, in the c/c++, it does not support dynamic size of static memory allocation, so, you just modify your code like this.
int x;
cin >>x;
int** mat = new int[x][x];
I have a simple point class:
class Point {
public:
Point(const double, const double);
/** This constructor creates invalid point instance **/
Point();
~Point();
const double x;
const double y;
/** This returns true if one of the values is NaN **/
bool isInvalid() const;
/** Returns true if coordinates are equal **/
bool equal(const Point& p) const;
};
Values x and y are const so that I can be sure they never change. They are supposed to be always constant. The problem is I can't assign to variables holding Point:
Point somePoint;
... meanwhile, things happen ...
//ERROR: use of deleted function 'Point& Point::operator=(const Point&)'
somePoint = Point(x, y);
I understand that assigning is a problem because somePoint.x = something is forbidden. I need to use point to hold last point value during rendering:
Point lastPoint;
PointInGraph* point = graphValues.last;
while((point = point->next())!=nullptr) {
// calculate pixel positions for point
double x,y;
...
if(!lastPoint.isInvalid())
drawer.drawLine(round(lastPoint.x), round(lastPoint.y), round(x), round(y));
// ERROR: use of deleted function 'Point& Point::operator=(const Point&)'
lastPoint = Point(x, y);
}
So does const in class properties simply make any variable of that class type const as well? Or is there a workaround?
It's not possible. It would require modifying const values.
Instead of making x and y themselves const, make them non-const but provide a const interface to them, i.e. by making them private and providing const getters.
Instead of making the variables const you could just not provide any way for the user to change the values by:
making them private
only allowing assignment to a another instance as the only way to change the values.
You can see how this would work in the following example:
#include <iostream>
class Point {
public:
Point(const double x_ = 0, const double y_ = 0) : x(x_), y(y_) {}
double getX() const { return x; }
double getY() const { return y; }
private:
double x;
double y;
};
int main()
{
Point a{1,5};
Point p;
p = a;
std::cout << p.getX() << ", " << p.getY(); // no error here
//p.x = 5; // error here now
//p.y = 7; // error here now
}
Live Example
If you un-comment the last two lines you will get an error to prove that you cannot change x and y.
Actually it's, of course, possible by directly technique called cast away constness which is a known loophole in const mechanic in C++. Basically I can abuse the fact that const int* can be assigned to int* variable. The possible solution:
Point& Point::operator=(const Point& p)
{
*((double*)&x)=p.x;
*((double*)&y)=p.y;
}
This is of course not recommended, but I'm not the one of the people who think that knowledge is dangerous.
In STL, list is a data structure that automatically sort the numbers by their values. If the elements are not numbers but instances of a class, and I want the container to automatically sort the elements by the value of a member of the class, what kind of container should I use? e.g.
class Rect{
double height;
double width;
double area;
};
I want the container to automatically sort by area of the rectangle.
You have std::multiset for auto-ordering container:
std::multiset<Rect, LessArea> rects;
with LessArea
struct LessArea
{
bool operator ()(const Rect& lhs, const Rect& rhs) const
{
return lhs.area < rhs.area;
}
};
stl::priority_queue is what you want. Just define an ordering on Rects with less<Rect> or specialize stl::priority_queue for Rect.
If you want to sort automatically , you have to do what is called
1) Operator Overloading of less than < operator
2) Comparator function
And for your task , to automatically sort , AFTER you have written a comparison function or overloaded the < operator , You can use either
STL set or priority queue . These two data structures are defined to automatically sort the elements based on the comparison function. But a note here is that you can't insert duplicate elements in
set , that is if area of your two rectangle is same , then the first one of those rects will be saved in the set. And second one can't be inserted.
Program using std::set will look like below .
class Rect{
double height;
double width;
double area;
public:
bool operator<( const Rect& rhs ) const
{ return area < rhs.area; }
};
You need to define "<" operator for comparison .
Please note : std::set will not allow multiple copies of same object .you can have only unique elements inside set .
I don't mind using a vector, especially if you want to be able to store duplicate elements. By using a simple lambda function, we can sort the objects by whatever member of a Rect we want. In this example, I chose to sort Rect objects by area.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
class Rect {
Rect(double height, double width, double area) {
_height = height;
_width = width;
_area = area;
}
double area() const {
return _area;
}
// sorts Rect objects by ascending order of area
static void sort_by_area(vector<Rect> &shapes) {
sort(shapes.begin(), shapes.end(), [](const Rect &first, const Rec &second)
{ return first.area() < second.area); });
}
private:
double _height;
double _width;
double _area;
};
int main() {
vector<Rect> r;
r.push_back(Rect(0,0,3));
r.push_back(Rect(0,0,2));
r.push_back(Rect(0,0,4));
for(auto &obj : r) {
//prints 3 2 4
cout << obj.area() << endl;
}
Rect::sort_by_area(r);
for(auto &obj : r) {
//prints 2 3 4
cout << obj.area() << endl;
}
return 0;
}
I would like to have an insight about whenever I should be using references or pointers.
Let's take the example of a Polygon class using a Rectangle class for its internal bounding box.
Polygon.h
class Polygon {
private:
std::list<Point> _points;
Rectangle _boundingBox;
public:
Polygon(const std::list<Point> &);
public:
const std::list<Point> &getPoints() const;
const Rectangle &getBoundingBox() const;
private:
void setBoundingBox();
};
Polygon.cpp
#include <iostream>
#include "Polygon.h"
Polygon::Polygon(const std::list<Point> &points)
{
if (points.size() < polygon::MIN_SIDE + 1) {
throw std::invalid_argument("A polygon is composed of at least 3 sides.");
}
if (points.front() != points.back()) {
throw std::invalid_argument("A polygon must be closed therefore the first point must be equal to the last one.");
}
std::list<Point>::const_iterator it;
for (it = ++points.begin(); it != points.end(); ++it) {
this->_points.push_back(*it);
}
this->setBoundingBox();
}
void Polygon::translate(const std::array<float, 2> &vector)
{
std::list<Point>::iterator it;
for (it = this->_points.begin(); it != this->_points.end(); ++it) {
(*it).setX((*it).getX() + vector[0]);
(*it).setY((*it).getY() + vector[1]);
}
Point topLeft = this->_boundingBox->getTopLeft();
Point bottomRight = this->_boundingBox->getBottomRight();
topLeft.setX(topLeft.getX() + vector[0]);
topLeft.setY(topLeft.getY() + vector[1]);
bottomRight.setX(bottomRight.getX() + vector[0]);
bottomRight.setY(bottomRight.getY() + vector[1]);
}
const std::list<Point> &Polygon::getPoints() const
{
return this->_points;
}
const Rectangle &Polygon::getBoundingBox() const
{
return this->_boundingBox;
}
void Polygon::setBoundingBox()
{
float xMin = this->_points.front().getX();
float xMax = this->_points.front().getX();
float yMin = this->_points.front().getY();
float yMax = this->_points.front().getY();
std::list<Point>::const_iterator it;
for (it = this->_points.begin(); it != this->_points.end(); ++it)
{
Point point = *it;
if (point.getX() < xMin) {
xMin = point.getX();
}
if (point.getX() > xMax) {
xMax = point.getX();
}
if (point.getY() < yMin) {
yMin = point.getY();
}
if (point.getY() > yMax) {
yMax = point.getY();
}
}
this->_boundingBox = new Rectangle(Point(xMin, yMin), Point(xMax, yMax));
}
std::ostream &operator<<(std::ostream &out, const Polygon &polygon)
{
std::list<Point>::const_iterator it;
for (it = polygon.getPoints().begin(); it != polygon.getPoints().end(); ++it) {
out << (*it);
if (it != polygon.getPoints().end()) {
out << " ";
}
}
return out;
}
Rectangle.h
#pragma once
#include <stdexcept>
#include "Point.h"
class Rectangle {
private:
Point _topLeft;
Point _bottomRight;
public:
Rectangle(const Point &, const Point &);
public:
const Point &getTopLeft() const;
const Point &getBottomRight() const;
float getWidth() const;
float getHeight() const;
};
Rectangle.cpp
#include "Rectangle.h"
Rectangle::Rectangle(const Point &topLeft, const Point &bottomRight)
{
if (topLeft.getX() > bottomRight.getX() || topLeft.getY() > bottomRight.getY()) {
throw std::invalid_argument("You must specify valid top-left/bottom-right points");
}
this->_topLeft = topLeft;
this->_bottomRight = bottomRight;
}
const Point &Rectangle::getTopLeft() const
{
return this->_topLeft;
}
const Point &Rectangle::getBottomRight() const
{
return this->_bottomRight;
}
float Rectangle::getWidth() const
{
return this->_bottomRight.getX() - this->_topLeft.getX();
}
float Rectangle::getHeight() const
{
return this->_bottomRight.getY() - this->_topLeft.getY();
}
Point.h
#pragma once
#include <ostream>
#include <cmath>
class Point {
private:
float _x;
float _y;
public:
Point(float = 0, float = 0);
public:
float distance(const Point &);
public:
float getX() const;
float getY() const;
void setX(float);
void setY(float);
};
std::ostream &operator<<(std::ostream &, const Point &);
bool operator==(const Point &, const Point &);
bool operator!=(const Point &, const Point &);
Point.cpp
#include "Point.h"
Point::Point(float x, float y)
{
this->_x = x;
this->_y = y;
}
float Point::distance(const Point &other)
{
return std::sqrt(std::pow(this->_x - other.getX(), 2) + std::pow(this->_y - other.getY(), 2));
}
float Point::getX() const
{
return this->_x;
}
float Point::getY() const
{
return this->_y;
}
void Point::setX(float x)
{
this->_x = x;
}
void Point::setY(float y)
{
this->_y = y;
}
std::ostream &operator<<(std::ostream &out, const Point &point)
{
out << "(" << point.getX() << ", " << point.getY() << ")";
return out;
}
bool operator==(const Point &p1, const Point &p2)
{
return p1.getX() == p2.getX() && p1.getY() == p2.getY();
}
bool operator!=(const Point &p1, const Point &p2)
{
return p1.getX() != p2.getX() || p1.getY() != p2.getY();
}
A lot of questions come with this snippet of code.
This does not compile because obviously whenever we try to create a Polygon, it ends up trying to create a Rectangle with a default constructor which does not exist.
I can't use initializer list because obviously the bounding box depends on some computed values from my list of points.
I could create a default constructor creating two Point(0, 0) by default for the Rectangle but this does not make much sense.
I could use pointers but then I feel this is not the nicest solution as I tend to think this is mostly used for polymorphism in C++ we should prefer reference whenever possible.
How should I then proceed ?
I feel I am missing something out about C++ and could learn a lot from this.
I think your main question is about how to deal with the problem of needing to initialize both std::list<Point> _points; and Rectangle _boundingBox;, while also doing some validation of _points.
The simplest solution is to just give Rectangle a default constructor (or pass two default Points as initializer). Then once you have validated the points argument in the constructor, you calculate the Rectangle based on the points.
A slightly more complicated alternative is to allow the validation function to be invoked from the ctor-initializer list, e.g.:
Polygon::Polygon(std::list<Point> points)
: _points( validate_point_list(points), std::move(points) ), _boundingBox( calculateBoundingBox(_points) )
{
}
where you have functions (which could be free functions):
void validate_point_list(std::list<Point> &points)
{
if (points.size() < polygon::MIN_SIDE + 1)
throw std::invalid_argument("A polygon is composed of at least 3 sides.");
if (points.front() != points.back())
throw std::invalid_argument("A polygon must be closed therefore the first point must be equal to the last one.");
// caller must pass in same first and last point, but we only store one of the two
points.erase( points.begin() );
}
and
Rectangle calculateBoundingBox(std::list<Point> const &_points)
{
// whatever logic you have in setBoundingBox, except return the answer
}
Note that the loop in your Polygon constructor is unnecessarily complicated. You could have just written _points = points; and then erased the extra point (which is O(1) for lists).
Note that I have passed by value and then used std::move. The reason is that if the argument given is a rvalue then it can just be moved right on through into where it's being stored; whereas with the const & version, a copy is stored and then the original is destructed.
I would use const & a lot less than you did. Small objects , such as Point and Rectangle, don't suffer a performance penalty from pass-by-value (and might even be more efficient that way). And as mentioned in the previous paragraph; if your function accepts a parameter and it is going to take a copy of that parameter, it's better to pass by value .
Passing by reference is best only when you are using but not storing the values passed. For example, calculateBoundingBox.
Finally, once you get this working, you might want to think about having the Polygon constructor accept an iterator pair of points range, and/or a std::initializer_list.
I would defined a default constructor for Rectangle class as private and I would make Polygon class a friend of Rectangle class:
class Rectangle {
friend class Polygon;
Point _topLeft;
Point _bottomRight;
Rectangle(); // accessible only to friends
public:
Rectangle(Point const&, Point const&);
...
};
And then in setBoundingBox():
void Polygon::setBoundingBox() {
...
_boundingBox._topLeft = Point(xMin, yMin);
_boundingBox._bottomRight = Point(xMax, yMax);
}
Thus, I wouldn't expose the default constructor of Rectangle and at the same time I would have a concrete object which is more efficient in terms of cache performance.
I feel as though you should have a separate class called BoundingBox that
1) Takes a collection of points in its constructor
2) Is inherited from Rectangle
Meanwhile, Rectangle should have a state, along the lines of NOT_A_RECTANGLE or it could throw an exception. Just be sure you clean up when throwing exceptions from a constructor.
Then you would construct the bounding box as part of the construction of the polygon and you can verify that a bounding box is possible as part of your error checking. (probably rather than 3 sides check, but I am no geometry expert)
BoundingBox would remain a member of Polygon.
This would be more RTTI.
It occurs to me though, that if you translate or rotate the polygon, you've also go to translate or rotate the bounding box. You might want to consider making the list of points its own object and sharing them. This would be a more advanced topic. You can for now get away with just recalculating the bounding box on operations performed upon the polygon.
As to whether to use a reference, a pointer, or pass by value, I don't know that there is a black and white list of things to consider for this, but a few are:
Is the object large enough to even worry about it? A rectangle is 4 floats?
Are there interfaces or base classes you will need to cast to, rather than always using the class itself? If so, you've got no choice but to use a pointer of some sort. The pointer could be unique, shared, weak, etc. depending on the situation. You have to ask yourself who owns it, whats the life time, and are there circular references?
Most people will probably use a reference whenever possible rather than a pointer, but only when passing by value doesn't qualify.
IMO, since you are just "GetBoundingBox", I think it would be simple and more maintainable to just return a copy of the bounding box by value rather than some const reference and definitely more than a pointer.
One solution would be to write a programmatic constructor for Rectangle that takes as its argument a const std::list<Point>&. It could traverse the list once, computing the maximum and minimum x and y. Then, your Polygon constructor would become:
Polygon::Polygon(const std::list<Point> &points)
: _points(points),
: _boundingBox(points)
{
// ...
}
An alternative is to move the code to find the bounding box from a list of points to a helper function, then define a move constructor Rectangle::Rectangle( Rectangle&& x ). In that case, your Polygon constructor would be:
Polygon::Polygon(const std::list<Point> &points)
: _points(points),
: _boundingBox( findBoundingBox(points) )
{
// ...
}
Either way, you could update a bounding box with assignment, so you might want an assignment operator like Rectangle& Rectangle::operator= ( Rectangle&& x ) to make that more efficient. You can skip the Rectangle&& versions if a Rectangle is just Plain Old Data. But if you do this a lot, you might overload Rectangle& findBoundingBox( const std::list<Point>& src, Rectangle& dest ) to update in place with no copying.
On a minor side note, I’d discourage you from using identifiers that begin with underscores, since those names are reserved in the global namespace in C++, and your libraries might declare something named _point.
I need to complete the Rectangle class. Write 3 constructors and a destructor to satisfy the main() below. Use constructor initializers for each constructor.
This is what is done:
class Rectangle
{
float* length;
float* width;
...
???
...
};
int main()
{
Rectangle r1;
Rectangle r2(4.5,2.3);
Rectangle r3(r2);
}
This is how I filled up the rectangle class:
class rectangle
{
private:
float* length;
float* width;
public:
rectangle(); //default constructor
rectangle(double w, double l); //constructor with parameters
rectangle(const rectangle&); //copy constructor
~rectangle(void);
double getWidth(void);
double getLength(void);
double perimeter(void) const;
double area(void) const;
};
...........
...........
...........
int main()
{
rectangle r1;
rectangle r2(4.5,2.3);
rectangle r3(r2);
//statements
}
I just want to know if am doing it right or wrong. Can anyone see if am missing smth or need to add to rectanglr class?!
I think that you are doing wrong because the definition
Rectangle r2(4.5,2.3);
does not have a corresponding constructor. Also take into account that the class in the assignment is named as Rectangle not rectangle.:)
I think that instead of length and width (why did you declare them as pointers?!) you should define four data members that will denote four points of the rectangle.
The declaration and the uses of the three constructors (default constructor, a custom constructor, and a copy constructor) look reasonable. Storing pointers to float does not look reasonable, however: you should just store floats (I would actually store doubles unless I have a reason to assume that there are a huge mount of rectangles). When storing floats, there is actually no need to have a copy constructor or a destructor. If you insist in storing float* and, thus, allocate memory, you shall also implement a copy assignment:
rectangle& rectangle::operator= (rectangle other) {
other.swap(*this);
return *this;
}
void rectangle::swap(rectangle& other) {
std::swap(this->length, other.length);
std::swap(this->width, other.width);
}