This question already has answers here:
Can a local variable's memory be accessed outside its scope?
(20 answers)
Closed 5 years ago.
This is my main function:
int main(){
Complex c1(1.0, 5.0);
Complex c2(3.0,-2.0);
Complex c3(1.0, 2.0);
cout << "c1 + c2 + c3 = "
<< c1 + c2 + c3 << endl;
return 0;
}
This is the function I use to add up the required numbers
Complex& operator+(const Complex & x, const Complex & y){
Complex c;
c.a = x.a + y.a;
c.b = x.b + y.b;
return c;
}
a and b are private double variables in my class.
On running my program, I seem to get the output as 1+2i ie(c3) and it only seems to work properly when I add only 2 objects. Is there any way I can tweak my existing code to allow it to work for up-to n terms?
Your operator + returns a reference to the local variable c, which gets destroyed after it is done. Any further use of the result leads to undefined behavior.
You need to return a value, so it gets copied (or a rvalue), but not a reference:
Complex operator+(const Complex & x, const Complex & y)
{...}
Related
This question already has answers here:
What is a lambda expression in C++11?
(10 answers)
Closed 1 year ago.
I saw an snippet CC source such as.
imagecb = [ &, xx, yy, zz] (uint32_t a1, int a2) {
...
}
I did know what is symbol of & in the array
this syntax declare an inline functions with 2 arguments a1, a2, right?
it is not the array, it is a lambda expression. Between [] you pass elements from another scope that you need inside expression. & means to get all elements that you need by reference.
In this specific case, variables xx, yy, zz will be copied, but if let's say this lambda expression uses another variable like for example aa it will be passed by reference.
It is worth mentioning that even if the element is passed by reference to a lambda expression, it cannot be modified (in default). To allow modification you need to use keyword mutable
Little code sample:
int xx=0, yy=0, zz=0;
int aa=1;
auto imagecb = [&, xx, yy, zz](uint32_t a1, int a2) mutable {
cout << aa;
aa++;
return aa;
};
cout << endl<<imagecb(2, 3);
I am following this tutorial on operator overloading: https://www.geeksforgeeks.org/operator-overloading-c/
Code snippet:
class Complex {
private:
int real, imag;
public:
Complex(int r = 0, int i = 0) { real = r; imag = i; }
// This is automatically called when '+' is used with
// between two Complex objects
Complex operator + (Complex const& obj) {
Complex res;
res.real = real + obj.real;
res.imag = imag + obj.imag;
return res;
}
void print() { cout << real << " + i" << imag << endl; }
};
int main()
{
Complex c1(10, 5), c2(2, 4);
Complex c3 = c1 + c2;
c3.print();
}
My question is, how does c++ know what to pass in to &obj and how does it know what to give to real and imag within the operator function? Like how does it know 10 for c1 goes to real and 2 for c2 goes to obj.real? It was never specified which object gets assigned to obj. Hell how does it even know to parse c1's values to real and imag within the operator function?
c1 is the object you're working with. That probably sounds confusing, so let me explain.
When you do this:
c1 + c2;
ignoring the return value for a second, that code is the same as doing this:
c1.operator+(c2);
So, c1 is the base object on which the operator is called. In the same way that c1.print() uses c1's values, calling the operator uses c1's values by default, so to speak.
Why is c1 called here and not c2? Like why isn't it the same as:
c2.operator+(c1);
This is because c1 is on the left hand side. If c2 were on the left hand side, like in the example c2+c1, then operator+() would get called on c2 instead.
So, in short (and other words), C++ uses operator+()(and similar operators) by calling operator+() in the following format:
left.operator+(right);
This allows you to use real and imag like you would in print() for the left side's member variables, and other.real and other.imag for the right side's variables.
So, in the comments you asked a couple more questions that I figure might take more than a comment or two to answer, but are worth answering. So, here goes.
So if you call that + function, it ignores the c3 which I actually assumed was what we were working with, and looks at the left and right hand side of the operation to know what to assign to each side?
Correct. As far as inside the function, operator+() only looks at the objects immediately beside it (in this case, c1 and c2) to perform the calculation.
I am surprised because c3 technically is what I am working with,
Ah, okay. Not for the calculation itself. Let's look at your operator+() closely again:
Complex operator + (Complex const& obj) {
Complex res;
res.real = real + obj.real;
res.imag = imag + obj.imag;
return res;
}
Here, you have a current object (which is where real and imag come from) and another object (which is where obj.real and obj.imag come from). It's these that make up c1 and c2. These are the numbers you are actually adding.
c3, on the other hand, is the result of this addition. If I have something like this:
4 + 3 = 7
The operation 4+3 will have a result: 7. That's what c3 is here. Well, technically, that's what res is here. By returning res, you're returning the result. And in the case of c3, it's setting it's value to the returned result of operator+() via the assignment (=) operator.
Secondly, why do I need to return res?
Already sort of covered that, but to be clear: res is the result of the operation. C++ wouldn't know how to get the result otherwise.
res is only a local variable, wouldn't it's data get destroyed once + is done, instead of it passing the summation data to real and imag?
You seem to be confusing returning by reference and returning by value. If you return a local variable by reference, absolutely. This will get destroyed. However, if you return by value, the result gets copied out almost by definition, so you're totally fine here in this example.
This question already has answers here:
What are the basic rules and idioms for operator overloading?
(8 answers)
Why pass by const reference instead of by value?
(8 answers)
Closed 3 years ago.
I just learnt the basics of operator overloading. After which I wrote the following code for vector addition of two points in a plane.
#include <bits/stdc++.h>
using namespace std;
struct point{
int x, y;
point operator+(point b){
point c;
c.x = x + b.x;
c.y = y + b.y;
return c;
}
};
int main()
{
point a, b, c;
a.x = 1, a.y = 2, b.x = 3, b.y = 4;
c = a + b;
cout<<c.x <<" "<< c.y;
return 0;
}
However most of the other operator overloading examples I find are coded very differently, example answers to this question. Even though I am getting the correct output using this, is there a cause for concern when I do it this way by declaring a new variable, or leaving out const?
This question already has answers here:
Casting double array to a struct of doubles
(6 answers)
Closed 3 years ago.
I was toying around with a class where I wanted to index into it with an operator[], while also being able to access the fields.
I've attached an MCVE below of what I'm trying to do, which is be able to access a member variable through the variable itself, but also with some pointer offsets (ex: if there's an a, and b, then I can access b by the name, or access it by &a + 1 if they're the same type and located sequentially without padding).
I'm worried that I'll be running into undefined behavior and won't know it. Originally I was trying to do a "union with 1) members that are floats, and 2) array of floats" but I found out that it's undefined behavior. I tried looking up in the standard if what I'm about to do below is undefined behavior but wasn't able to find it (which obviously does not mean it doesn't exist, I easily could have missed it).
Since I'm also using CRTP to do this, I figure since I'm casting to itself that it should be okay as long as inheritance doesn't provide any members.
To make sure that this is possibly legal in C++, I added a bunch of static asserts which:
Make sure it's a standard layout, so I can use offsetof for other static asserts static_assert(std::is_standard_layout_v<Color>);
Make sure it's trivial static_assert(std::is_trivial_v<Color>);
Make sure the offsets are sequential static_assert(offsetof(Color, r) == 0);, static_assert(offsetof(Color, g) == sizeof(float));, static_assert(offsetof(Color, b) == 2 * sizeof(float));
Make sure nothing was added to the class from inheriting static_assert(sizeof(Color) == 3 * sizeof(float));
The code:
#include <iostream>
using namespace std;
template <typename T>
class ColorCRTP {
T& getInstance() {
return *static_cast<T*>(this);
}
public:
// Is it UB to do this when we set values from the
// fields themselves in the actual class?
float& operator[](size_t index) {
// Assume the inheriting class *always* is only a
// series of sequential members of the exact same
// type.
return *(&getInstance().r + index);
}
};
struct Color : ColorCRTP<Color> {
float r;
float g;
float b;
Color() = default;
Color(float r, float g, float b) : r(r), g(g), b(b) { }
};
// Do these help guarantee that I am not performing UB?
static_assert(std::is_standard_layout_v<Color>);
static_assert(std::is_trivial_v<Color>);
static_assert(offsetof(Color, r) == 0);
static_assert(offsetof(Color, g) == sizeof(float));
static_assert(offsetof(Color, b) == 2 * sizeof(float));
static_assert(sizeof(Color) == 3 * sizeof(float));
int main() {
Color c{0.5f, 0.75f, 1.0f};
c.g = 0.123f;
cout << c[1] << " = " << c.g << endl;
c[1] = 0.321f; // This is legal or UB?
cout << c[1] << " = " << c.g << endl;
}
Am I violating the standard and invoking undefined behavior by doing the above? Assuming no out-of-range indices are provided of course.
Since r is the first member, I don't know if 6.7.2 part 4.3 gives me further comfort in the fact that I'm referencing the first member in a safe way or not.
The behaviour of your program is undefined.
Pointer arithmetic is only valid within arrays. And r, g, b do not form an array.
Your best bet is to recode float& operator[](size_t) with a switch block comprising 3 labels.
Putting all the maintainability and reading issues aside, can these lines of code generate undefined behavior?
float a = 0, b = 0;
float& x = some_condition()? a : b;
x = 5;
cout << a << ", " << b;
No, it's just fine. It would not create undefined behavior in this code. You will just change value of a or b to 5, according to condition.
This is absolutely fine, as long as both sides of the conditional are expressions that can be used to initialize a reference (e.g. variables, pointer dereferences, etc)
float& x = some_condition()? a : *(&b); // This is OK - it is the same as your code
float& x = some_condition()? a : b+1; // This will not compile, because you cannot take reference of b+1