const pointer members and operator= - c++

class Point {
public:
Point(int x, int y) : { x = new int(x); y = new int(y) }
...
...
Point& operator=(const Point& other) {
if(this!=&other){
delete x;
delete y;
x = new int(*other.x);
y = new int(*other.y);
}
return *this;
}
private:
const int* x;
const int* y;
}
Will this implementation of operator= work even if x and y of this were already initialized? does deleting a const pointer allow us to reassign it?

That's not a const pointer, but a pointer to const. So you can modify the pointer, you can't that which it points to.
A const pointer is
int* const x;
and your code wouldn't compile then.

Related

C++ use std::fill for class with deleted assign operator

Suppose I have a range of objects
class X {
public:
X()
: X(0) {
}
X(size_t num)
: x_(num) {
}
X(const X& other) = delete;
X& operator=(const X& other) = delete;
X(X&& other) {
x_ = exchange(other.x_, 0);
}
X& operator=(X&& other) {
x_ = exchange(other.x_, 0);
return *this;
}
size_t GetX() const {
return x_;
}
private:
size_t x_;
};
With this in mind I can't use std::fill as operator= is deleted. What is the right way to fill the range for this kind of object?
Source object of std::fill is const. const object cannot be used as source of move operation.
You can add helper class with conversion operator to X, every time when *first = value; (look at possible implementation of std::fill) is called, temporary of X is returned and move operation is performed:
template<size_t N>
struct Helper {
X MakeTemp() const { return X(N); }
operator X () const { return MakeTemp(); }
};
int main(){
std::vector<X> v;
v.resize(10);
std::fill(v.begin(), v.end(),Helper<10>{});
Demo

Including const in operator overloading argument list gives error (C++)

I am trying out with operator overloading, for which I wrote below code
class OwnClass
{
private:
int x,y;
public:
OwnClass(int x, int y) { SetX(x); SetY(y); }
int GetX() { return x; }
void SetX(int x) { this->x = x;}
int GetY() { return y; }
void SetY(int y) {this->y = y;}
OwnClass& operator + (const OwnClass &o) // Problematic line
{
this->x += o.GetX();
this->y += o.GetY();
return *this;
}
};
When compiled, following error is shown
fun.cpp(65): error C2662: 'OwnClass::GetX' : cannot convert 'this'
pointer from 'const OwnClass' to 'OwnClass &'
Conversion loses qualifiers
fun.cpp(66): error C2662: 'OwnClass::GetY' : cannot convert
'this' pointer from 'const OwnClass' to 'OwnClass &' Conversion loses
qualifiers
When I modify the code as under, it compiles fine.
OwnClass& operator + (OwnClass &o) // removed const
{
this->x += o.GetX();
this->y += o.GetY();
return *this;
}
I could not understand why so ? I mean I am not able to understand the compiler error.
The parameter o is declared as reference to const, which can't be called with GetX and GetY, because they're non-const member function. You can (and should) change them to const member functions to solve the issue.
int GetX() const { return x; }
int GetY() const { return y; }
BTW: In general binary operator+ is not supposed to return a reference to non-const. It's better to return a new object by value.
OwnClass operator + (const OwnClass &o) const
{
OwnClass r(GetX(), GetY());
r.x += o.GetX();
r.y += o.GetY();
return r;
}
Note for this case operator+ could (and should) be declared as const member function too. And as #M.M suggested, making it non-member function would be better.
The problem is that you are calling non-const member functions on const objects. Make getters const to fix this problem:
int GetX() const { return x; }
int GetY() const { return y; }

Overloading subscription operator() or [] with no code repetition

I have two versions of operator():
const A& operator(int x ,int y) const;
A& operator(int x ,int y);
But I don't know what would be the best way to avoid code repetition (because they essentially have the same logic).
I did read the awesome FAQ regarding operator overloading (and some other questions) but did not find answer.
EDIT_1: I've tried the suggestion that Skizz proposed but something like that does not quite work for me but maybe I've missed something:
Because this works while this does not compile giving the following error:
error: invalid initialization of reference of type ‘int&’ from expression of type ‘const value_type {aka const int}’
If both methods 'essentially have the same logic' then surely they should both be marked const. If they do behave differently, should they be called the same thing?
What you need is a third, hidden method that does the common thing, like this:-
const A& operator(int x ,int y) const
{
return Common (x,y);
}
A& operator(int x ,int y)
{
return Common (x,y);
}
A& Common (int x, int y) const
{
// common code
}
This takes advantage of the implicit non-const to const conversion. In the first method, the this object remains const in the call to Common but the non-const return value is converted to const. In the second, the non-const this object is converted to a const this object and the return object is unchanged.
If you have the data in question as shared/unique pointer, you are able to forward it to a common function:
class X {
public:
const A& operator () (int x ,int y) const {
common(data, x, y);
return *data;
}
A& operator () (int x ,int y) {
common(data, x, y);
return *data;
}
private:
void common(std::shared_ptr<T>, int x ,int y) const;
std::shared_ptr<A> data;
};
Now you are able to access the T* via data.get() which is 'T* get() const'.
(Note: I consider the common function a bad design)
You might do, also:
class X {
public:
const A& operator () (int x ,int y) const {
common(x, y);
return data;
}
A& operator () (int x ,int y) {
// ... make mutations
common(x, y);
// ... make mutations
return data;
}
void common(std::shared_ptr<T>, int x ,int y) const;
T data;
};
Or actually, making the data mutable, if it is not breaking logical const:
class X {
const A& operator () (int x ,int y) const {
// ... make mutations on the mutable data, only
return *lazy_evaluated_data;
}
A& operator () (int x ,int y) {
const X& self = *this;
self(x, y);
return *lazy_evaluated_data;;
}
private:
mutable T lazy_evaluated_data; // or a cache
};
Write a helper function and call it from both operators. You'll need to do some const_cast<...>(this) which can be ugly, but it's a common pattern.

How does this operator [ ] overloading works in this case?

I stumbled upon this class:
class Vec3f
{
...
float x, y, z;
...
};
inline float operator[](const int index) const
{
return (&x)[index];
}
inline float& operator[](const int index)
{
return (&x)[index];
}
The class is using the [] to access to x, y, z values as in an array so that
v[0] is the value in x, v[1] is the value in y, v[2] is the value in z, but
How does the return statement working?
Is it correct to read it like: "get the value in the address specified by index starting from the address of x"?
Do (&x) must be in parenthesis, otherwise it would return the value of the address of x[index], isn't it?
Technically this is not valid code.
But what is happening:
// Declare four variables
// That are presumably placed in memory one after the other.
float x, y, z;
In the code:
return (&x)[index];
// Here we take the address of x (thus we have a pointer to float).
// The operator [] when applied to fundamental types is equivalent to
// *(pointer + index)
// So the above code is
return *(&x + index);
// This takes the address of x. Moves index floating point numbers further
// into the address space (which is illegal).
// Then returns a `lvalue referring to the object at that location`
// If this aligns with x/y/z (it is possible but not guaranteed by the standard)
// we have an `lvalue` referring to one of these objects.
Its easy to make this work and be legal:
class Vec3f
{
float data[3];
float& x;
float& y;
float& z;
public:
float& operator[](const int index) {return data[index];}
Vec3f()
: x(data[0])
, y(data[1])
, z(data[2])
{}
Vec3f(Vec3f const& copy)
: x(data[0])
, y(data[1])
, z(data[2])
{
x = copy.x;
y = copy.y;
z = copy.z;
}
Vec3f& operator=(Vec3f const& rhs)
{
x = rhs.x;
y = rhs.y;
z = rhs.z;
return *this;
}
};

C++ operator for a = b .* c with pointers to a,b, and c objects as input

i have three pointers to three objects:
MyClass* a = new MyClass(...);
MyClass* b = new MyClass(...);
MyClass* c = new MyClass(...);
Now i want to specify an operator in MyClass so that I can do:
a = b*c;
So a,b, and c are already existing large objects which i do not want to make any additional copies of. I want to do the multiplication and directly write the result 'a'.
1) Is this even possible with c++ operators?
2) Could someone give me some hints at the syntax? (i'm a bit new to operators..)
Grateful for any help.
If you wrote operator* for MyClass.
MyClass* a = new MyClass(...);
MyClass* b = new MyClass(...);
MyClass* c = new MyClass(...);
you should use it like below:
*a = (*b) * (*c);
And you can not do it for pointers. For example this is impossible:
MyClass *operator*(const MyClass *a, const MyClass *b) // Impossible
{
...
}
Because the operator definition must have an argument of MyClass.
You really don't want to do this. Sticking with the standard way of defining operators for values and not pointers-to-values will make everything a lot cleaner and easier to maintain.
EDIT As aschepler points out in the comments you can't even do this. At least one of the arguments must be of a class type or a reference to a class.
If you want to avoid huge copy operations, you should use C++11 move semantics or emulate them through something like a MoveProxy or the Boost.Move support-library.
Example code:
// loads of memory with deep-copy
struct X {
int* mem;
X() : mem(new int[32]) { }
// deep-copy
X(const X& other)
: mem(new int[32]) { std::copy(other.mem, other.mem+32, this.mem); }
~X() { delete[] mem; }
X& operator=(const X& other) { std::copy(other.mem, other.mem+32, this.mem); return *this; }
X(X&& other) : mem(other.mem) { other.mem = nullptr; }
X& operator=(X&& other) { delete[] mem; this.mem = other.mem; other.mem = nullptr; return this; }
friend void swap(const X& x, const X& y)
{ std::swap(x.mem, y.mem); }
friend
X operator*(const X& x, const X& y)
{ return X(); }
};