C++, operator [], and tracking a change - c++

I'm trying to build a little array-ish class, like so:
class dumb
{
bool mChanged=false;
int mData[1000];
int& operator [](int i) {return mData[i];}
};
Here's my question-- is there any kind of hack or trick I could do so that if I did this:
dumb aDumbStuff;
aDumbStuff[5]=25; <- now mChanged gets set to true!
So basically, I want my class's mChanged value to go true if I modify any content. Any way to do this without making the array itself an array of objects that they themselves track getting changed, or by doing memcmps to see if things changed at all?
Some complex dance of assignment operators that would let my class detect "[n]=" happening?

The usual solution is to use a helper class, something like:
struct inner_ref {
dumb &me;
int i;
inner_ref(dumb &, int);
operator int();
dumb &operator=(int);
};
The operator[] overload returns this object, constructing it using a reference to *this, and the passed-in array index. Its operator= overload executes the actual assignment and also sets this flag. Its operator int() provides the appropriate semantics when [] is used to access the array's value, rather than modifying it.

You could set the flag to 'changed' inside your existing operator[] method, and add a second version with const returning an int (= not as a reference):
int operator [](int i) const {return mData[i];}
The compiler would pick the right one - modifying or not, as needed!

Related

Copy of a constant?

Polynomial operator + (const Polynomial& p);
//Adds existing Polynomial to p, returning the result
So because we can't change the value of a const, is there a way to make a copy of this p to allow me to access the functions of p?
Sorry guys at work and quite display the entire program, but in Poly.H in the private field it reads:
private:
List < Term > poly
So in PolyTest.cpp
If I need two polynomials
p_add = poly1 + poly2
I need to write the function in the operator+ to add like terms. Hope this is helpful.
If you need to make a copy then just copy it in the function
Polynomial operator + (const Polynomial& p);
{
Polynomial copy = p;
// do stuff
}
Now just because p is const doesn't mean you cannot use its members/functions. A typical operator+ would look like
Something operator + (const Something& s);
{
return Something(this->some_memeber + s.some_memeber,
this->another_memeber + s.another_memeber);
}
If you need a copy inside operator+, the most straightforward way of doing it is to pass p by (const) value:
Polynomial operator+ (Polynomial p);
Now p is a copy of the object you passed in that you can mess up with inside operator+. Of course if you pass by const value like
Polynomial operator+(const Polynomial p);
then the copy itself will be const, so you will be able to access only its const member functions.
As mentioned in the comments, sometimes passing by const reference and making sure that you only access the const member function is what you actually need, since you avoid the additional copy. However there are situations when a copy is necessary (most likely not here), such as when implementing the famous copy-and-swap idiom, in which case passing the object by value is the way to go, and the least verbose way of achieving the desired effect.
From the sound of it, you’re missing a const specifier on some member functions of Polynomial, e.g., you might have:
// Can modify *this.
std::vector<double> coefficients() { … }
When you need:
// Cannot modify *this.
std::vector<double> coefficients() const { … }
Adding the const specifier changes the type of this within the member function from Polynomial* to const Polynomial*. On a const reference, you can only invoke const member functions. (You can still invoke const member functions on a non-const reference.)
EDIT:
You are probably referring to the const specifier at the end of a member function like so:
class Test
// cannot modify members of Test
void test() const;
// can modify members of Test
void test2();
};
You can only call methods declared as const at the end when operating on a const object.
If you need to modify a member inside a const member function (which is not often the case) you can declare it as mutable
The const specifier in front of Polynomial& p means it is a const reference to a Polynomial and hence you cannot modify the value of p.
I has nothing to do with accessing functions. If the method is declared in your class you can ofc access all methods from the same class.
You can however make a simple copy to mess around with the copy but not the reference to the input paramter:
Polynominal p2(p);
or
Polynominal p3 = p;

Is there any way to copy some class and dont change the real one?

class A
{
// constructor,destructors and some getter and setter functions.
friend A& operator+(A& x,A& y);
}
class B
{
vector <A*> A_s;
}
Assume here is A n1*=new A("P"); and A n2*=newA("R"); ( No special meaning of P and R ,I just wrote that to indicate these two are different objects.After that i want to do that :
A final= *n1 +*n2; and i dont want to change final, if i changed n1 or n2 (or vice versa).Is there any way to do that ? (I have no copy constructor for that,there is just default copy constructor).Since the real code is realy long, i tried to simplfy it , sorry for any inconvenience.
First, the return type on your operator is probably wrong. You should return by value since you're returning a new object that's the sum of the other two. Also, you can take the first parameter by value and use that as working space to return. Finally you should take the second parameter by const reference, to avoid accidentally mutating your operands.
friend A operator+(A x, const A& y);
After that it's just up to your implementation of operator+ to not leave references back to x and y and what you want will happen automatically!

Best Way to Return a Class in C++

I'm writing a C++ vector class for a project and I'm having a hard time making a decision about how best to write some of the methods. Before I start I will say that the class has a good copy constructor and assignment operator (this will be relevant in a sec). The class has a set of static methods that return vectors when I want to make sure that neither parameter is altered, they have signatures like:
Vector* Vector::subtract(const Vector* v, const Vector* u)
{
double outX = v->myX - u->myX;
double outY = v->myY - u->myY;
double outZ = v->myZ - u->myZ;
return new Vector(outX, outY, outZ);
}
The problem I am having is that I don't want to return pointers if I can help it. So instead I did some testing and realized that if I just say
return Vector(outX, outY, outZ)
and then assign the result like
Vector foo = Vector::subtract(bar, temp)
it will create a copy and work fine. Here's where my question lies: I just called the constructor twice (essentially) is there a way to get around that? Secondly, if I use this method as a argument to another method like
foo.multiply(&Vector::subtract(foo, bar), 5)
will it still create a copy or did I just pass the pointer that has gone out of scope in the Vector::subtract method?
More generally, what is the best (or at least is there a better) way to do this?
I just called the constructor twice (essentially) is there a way to
get around that?
Have you ever heard of Return Value Optimization? There is nothing you have to do. The compiler will most likely eliminate the copy for you. Now, if you use C++11 and the Vector class manages a resource, you could declare a move constructor also, so that the returned value is moved just in case the compiler decides it cannot perform RVO. However, it looks like the class only holds 3 values, if that is the case, copying is going to be as efficient as moving.
&Vector::subtract(foo, bar)
What is the & for? Was that a mistake? Also, the member function is not declared static so the syntax is wrong. Anyways, assuming subtract returns a copy, it will return a copy and pass that to the multiply function as an argument.
Also, on another note, Vector* Vector::subtract(const Vector* v, const Vector* u)
would be better as Vector* Vector::subtract(const Vector& v, const Vector& u), this makes the syntax cleaner when you pass arguments to subtract, etc.
So changing your code, it would look something like the following:
Vector Vector::subtract(const Vector& v, const Vector& u)
{
return Vector(v.myX - u.myX, v.myY - u.myY, v.myZ - u.myZ);
}
Returning pointers/references to dynamically allocated objects is never the way to go. And obvious example would be if your function is called recursively, who is responsible for de-allocating that memory?
I've read from a book (by Scott Meyers, it was Effective C++ Item #21) that the only safe way to do it was to return the object itself. What you could do is, IIRC, facilitate the compilers job at eliminating these objects that are essentially temporare (returned from one function to be fed to another without every being assigned to another) and one of those ways was to make it anonymous (aka as the Return Value Optimization, thanks to In silico for reminding me). Like so
return Vector(outX, outY, outZ);
as opposed to:
Vector v(outX, outY, outZ);
return v;
So my proposed signature for your subtract method comes down to:
Vector Vector::subtract(const Vector& v, const Vector& u)
You should avoid pointers as much as possible, not only in the return type but also in arguments to functions. Prefer references whenever possible, use pointers when you must.
If you change your functions to take the arguments by reference and return by value. Consider overloading operators when it makes sense in the domain (which I believe is the case here):
class Vector { ... };
Vector operator+( Vector const& lhs, Vector const& rhs ) {
return Vector( lhs.x+rhs.x, lhs.y+rhs.y, lhs.z+rhs.y );
}
Vector operator*( Vector const& lhs, Vector const& rhs ) { ... }
Then you can chain operations at will:
Vector a(...), b(...);
Vector c = (a + b) * c;
Most compilers these days will implement what is called Return Value Optimization (RVO) to combat this problem. You're right that you shouldn't return pointers unless it's really necessary. That being said, you should probably be using references. All in all, if I was going to write this method, this is how I'd write it:
Vector Vector::subtract(const Vector& v, const Vector& u)
{
return Vector(v.myX - u.myX, v.myY - u.myY, v.myZ - u.myZ);
}

Overloading operator [] for both read and write

I'm having a trouble overloading operator [] for both read and write in my objects. This is a large code with different components and I'm not going to put all the details here since it wont help. In a nutshell what I have is the following
class MyObject(){
inline SetterProxy& operator[](int i) {
SetterProxy a(i);
return a;
}
inline double operator[](int i) const{
return some_value;
}
}
The first overloaded [] works fine for assigning values (if you are wondering what the SetterProxy is, I have to use Proxy classes to be able to do some checking and internal function calls before assigning values). However, the second one which should supposedly be called when reading does not work and the code crashes. I'm not sure what is happening here but when I comment out the first one it just works fine! Could it be that compiler somehow confuses the two since they are both inline?
Any thought would be appreciated.
EDIT:
Ok here is the SetterProxy itself:
class SetterProxy{
private:
Vec v;
int i;
double *ptr_val;
public:
inline SetterProxy(Vec v_, int i_) {
v = v_;
i = i_;
VecGetArray(v,&ptr_val);
}
inline ~SetterProxy(){
VecRestoreArray(v,&ptr_val);
}
inline void operator=(double rhs ){
ptr_val[i] = rhs;
}
};
Although I dont think its coming directly from that. Also initially I had it to return by value and I though changing it to reference would be more efficient. I think this should be safe since the assignment is done in the Proxy operator=() class and after that the proxy class goes out of scope. Either way, that does not save my problem!
You're returning a reference to a local variable - it goes out of scope when the operator returns, leaving your reference dangling. A good compiler should warn you about this if you turn the warning setting up to a reasonable level.
As noted in #Stuart Golodetz's answer, you are returning a reference to SetterProxy referring to a, which is local to your method and thus goes out of scope when it returns.
You should instead return a SetterProxy instance by value: that shouldn't be a big deal, SetterProxy will probably just hold the index and a reference to the "parent" object, so the compiler-generated copy constructor for it will be fine and the copy won't be costly at all.
By the way, unless you want to allow negative indexes, the usual idiom is to use size_t for indexes in arrays.

Using a class with const data members in a vector

Given a class like this:
class Foo
{
const int a;
};
Is it possible to put that class in a vector? When I try, my compiler tells me it can't use the default assignment operator. I try to write my own, but googling around tells me that it's impossible to write an assignment operator for a class with const data members. One post I found said that "if you made [the data member] const that means you don't want assignment to happen in the first place." This makes sense. I've written a class with const data members, and I never intended on using assignment on it, but apparently I need assignment to put it in a vector. Is there a way around this that still preserves const-correctness?
I've written a class with const data members, and I never intended on using assignment on it, but apparently I need assignment to put it in a vector. Is there a way around this that still preserves const-correctness?
You have to ask whether the following constraint still holds
a = b;
/* a is now equivalent to b */
If this constraint is not true for a and b being of type Foo (you have to define the semantics of what "equivalent" means!), then you just cannot put Foo into a Standard container. For example, auto_ptr cannot be put into Standard containers because it violates that requirement.
If you can say about your type that it satisfies this constraint (for example if the const member does not in any way participate to the value of your object, but then consider making it a static data member anyway), then you can write your own assignment operator
class Foo
{
const int a;
public:
Foo &operator=(Foo const& f) {
/* don't assign to "a" */
return *this;
}
};
But think twice!. To me, it looks like that your type does not satisfy the constraint!
Use a vector of pointers std::vector<Foo *>. If you want to avoid the hassle of cleaning up after yourself, use boost::ptr_vector.
Edit: My initial stab during my coffee break, static const int a; won't work for the use case the OP has in mind, which the initial comments confirm, so I'm rewriting and expanding my answer.
Most of the time, when I want to make an element of a class constant, it's a constant whose value is constant for all time and across all instances of the class. In that case, I use a static const variable:
class Foo
{
public:
static const int a;
};
Those don't need to be copied among instances, so if it applied, that would fix your assignment problem. Unfortunately, the OP has indicated that this won't work for the case the OP has in mind.
If you want to create a read-only value that clients can't modify, you can make it a private member variable and only expose it via a const getter method, as another post on this thread indicates:
class Foo
{
public:
int get_a() const { return a; }
private:
int a;
};
The difference between this and
class Foo
{
public:
const int a;
};
is:
The const int gives you assurance that not even the implementation of the class will be able to muck with the value of a during the lifetime of the object. This means that assignment rightfully won't work, since that would be trying to modify the value of a after the object's been created. (This is why, btw, writing a custom operator=() that skips the copy of a is probably a bad idea design-wise.)
The access is different – you have to go through a getter rather than accessing the member directly.
In practice, when choosing between the two, I use read-only members. Doing so probably means you'll be able to replace the value of an object with the value of another object without violating semantics at all. Let's see how it would work in your case.
Consider your Grid object, with a width and height. When you initially create the vector, and let's say you reserve some initial space using vector::reserve(), your vector will be populated with initial default-initialized (i.e. empty) Grids. When you go to assign to a particular position in the vector, or push a Grid onto the end of the vector, you replace the value of the object at that position with a Grid that has actual stuff. But you may be OK with this! If the reason you wanted width and height to be constant is really to ensure consistency between width and height and the rest of the contents of your Grid object, and you've verified that it doesn't matter whether width and height are replaced before or after other elements of Grid are replaced, then this assignment should be safe because by the end of the assignment, the entire contents of the instance will have been replaced and you'll be back in a consistent state. (If the lack of atomicity of the default assignment was a problem, you could probably get around this by implementing your own assignment operator which used a copy constructor and a swap() operation.)
In summary, what you gain by using read-only getters is the ability to use the objects in a vector or any container with value semantics. However, it then falls to you to ensure that none of Grid's internal operations (or the operations of friends of Grid) violate this consistency, because the compiler won't be locking down the width and height for you. This goes for default construction, copy construction, and assignment as well.
I'm considering making the data member non-const, but private and only accessible by a get function, like this:
class Foo
{
private:
int a;
public:
int getA() const {return a;}
};
Is this 'as good' as const? Does it have any disadvantages?
As of c++20, using const member variables are legal without restrictions that had made it virtually unusable in containers. You still have to define a copy assignment member function because it continues to be automatically deleted when a const object exists in the class. However, changes to "basic.life" now allow changing const sub-objects and c++ provides rather convenient functions for doing this. Here's a description of why the change was made:
The following code shows how to define a copy assignment member function which is useable in any class containing const member objects and uses the new functions std::destroy_at and std::construct_at to fulfil the requirement so the new "basic.life" rules. The code demonstrates assignment of vectors as well as sorting vectors with const elements.
Compiler explorer using MSVC, GCC, CLANG https://godbolt.org/z/McfcaMWqj
#include <memory>
#include <vector>
#include <iostream>
#include <algorithm>
class Foo
{
public:
const int a;
Foo& operator=(const Foo& arg) {
if (this != &arg)
{
std::destroy_at(this);
std::construct_at(this, arg);
}
return *this;
}
};
int main()
{
std::vector<Foo> v;
v.push_back({ 2 });
v.push_back({ 1 });
v.insert(v.begin() + 1, Foo{ 0 });
std::vector<Foo> v2;
v2 = v;
std::sort(v2.begin(), v2.end(), [](auto p1, auto p2) {return p1.a < p2.a; });
for (auto& x : v2)
std::cout << x.a << '\n';
}