How does v in float set(void) get initialized? [closed] - c++

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 16 days ago.
Improve this question
I am doing some online studying and this test question baffles me. I wrote it in VS and it gives a random number like 1295192591. This seems correct but the test claims the answer should be 2. That would be the correct answer but it appears that v is not initialized so its giving some random numbers from memory.
#include <iostream>
using namespace std;
class A{
public:
float v;
float set(float v){
A::v += 1.0;
return v;
}
float set(void) {
A::v = v + 1.0;
return 0.0;
}
float get(float v) {
v += A::v;
return v;
}
};
int main(void) {
A a;
cout << a.get(a.set(a.set()));
}
To fix this I added float v = 0;
Am I wrong to think the test is just wrong here or am I missing something? It appears it is instantiating A::v to v (which is unknown and not initialized) + 1.0; This produces unexpected results.
#include <iostream>
using namespace std;
class A{
public:
float v;
float set(float v){
A::v += 1.0;
return v;
}
float set(void) {
** float v = 0;**
A::v = v + 1.0;
return 0.0;
}
float get(float v) {
v += A::v;
return v;
}
};
int main(void) {
A a;
cout << a.get(a.set(a.set(a.set())));
}
Sorry, if this has been covered elsewhere.

the test claims the answer should be 2
The claim is wrong. The program has undefined behavior. A doesn't declare any constructors, so default-initialization of an automatic storage duration object of the type, such as A a;, will result in the member a.v having an indeterminate value.
Reading an indeterminate value (with very minor exceptions) causes undefined behavior. This happens here immediately in the most inner a.set()'s A::v = v + 1.0;.
Your modification adds a new local variable, also called v, but unrelated to A::v. This happens to give the program defined behavior, because now the first execution of A::v = v + 1.0; has v on the right-hand side refer to the function-local v with initialized value 0. As a consequence A::v is given a value without issue and that the rest of the member function calls may use.

Related

Storing reference in variable

I am new to C++. Say I have the following code:
vector<int> vec;
vec.push_back(5);
int x = vec.at(0);
From my understanding, x now represents a reference to the value in the vector. If this is the case, then why is it that if I were to have x = 7, the value in the vector would still be 5?
I tried searching on the site for a relevant thread, but did not see any that answered the question.
int x declares an integer. It is not a reference. In your code a copy is made of the value in the vector.
If you want a reference then you need to declare x as a reference to int:
#include <iostream>
#include <vector>
int main() {
std::vector<int> v{42};
int& x = v.at(0);
x = 5;
std::cout << v.at(0);
}
For further reading I suggest you pick a book and cppreference can be recommended very much https://en.cppreference.com/w/cpp/language/reference.

convenient Vector3f class

Sometimes there is a need to have a Vector3f class, which has x, y and z members, and can be indexed as a float[3] array at the same time (there are several questions here at SO already about this).
Something like:
struct Vector3f {
float data[3];
float &x = data[0];
float &y = data[1];
float &z = data[2];
};
With this, we can write this:
Vector3f v;
v.x = 2.0f;
v.y = 3.0f;
v.z = 4.0f;
glVertex3fv(v.data);
But this implementation is bad, because references take space in the struct (which is quite unfortunate. I don't see any reason why references cannot be removed in this particular case, maybe it is missed optimization from the compiler's part).
But, with [[no_unique_address]] I had this idea:
#include <new>
template <int INDEX>
class Vector3fProperty {
public:
operator float() const {
return propertyValue();
}
float &operator=(float value) {
float &v = propertyValue();
v = value;
return v;
}
private:
float &propertyValue() {
return std::launder(reinterpret_cast<float*>(this))[INDEX];
}
float propertyValue() const {
return std::launder(reinterpret_cast<const float*>(this))[INDEX];
}
};
struct Vector3f {
[[no_unique_address]]
Vector3fProperty<0> x;
[[no_unique_address]]
Vector3fProperty<1> y;
[[no_unique_address]]
Vector3fProperty<2> z;
float data[3];
};
static_assert(sizeof(Vector3f)==12);
So, basically, I have properties in the struct, which handles the access to x, y and z. These properties should not take space, as they are empty, and have the attribute of [[no_unique_address]]
What do you think about this approach? Does it have UB?
Note, this question is about a class, for which all these are possible:
Vector3f v;
v.x = 1;
float tmp = v.x;
float *c = v.<something>; // there, c points to a float[3] array
If this is going to live in a header, and you have some confidence in your compiler's optimizing capabilities, you can probably stick to a plain-old operator[]() overload and expect the compiler to be smart enough to elide the call and return the element that you want. E.g.:
class Vec3f {
public:
float x;
float y;
float z;
float &operator[](int i) {
if(i == 0) {
return x;
}
if(i == 1) {
return y;
}
if(i == 2) {
return z;
}
}
};
I tossed this into Compiler Explorer (https://godbolt.org/z/0X4FPL), which showed clang optimizing the operator[] call away at -O2, and GCC at -O3. Less exciting than your approach, but simple and should work under most circumstances.
But this implementation is bad, because references take space in the struct (which is quite unfortunate. I don't see any reason why references cannot be removed in this particular case, maybe it is missed optimization from the compiler's part).
This looks like a complicated issue. Standard-layout classes have to be compatible between each other. And so compilers are not allowed to eliminate any member, regardless of how they are defined. For non standard-layout? Who knows. For more info read this: Do the C++ standards guarantee that unused private fields will influence sizeof?
From my experience compilers never remove class members, even if they are "unused" (e.g. formally sizeof does use them).
Does it have UB?
I think this is UB. First of all [[no_unique_address]] only means that the member need not have a unique address, not that it must not have a unique address. Secondly it is not clear where your data member starts. Again, compilers are free to use or not paddings of previous [[no_unique_address]] class members. Meaning your accessors may access incorrect piece of memory.
Another problem is that you want to access "outer" memory from the "inner" class. AFAIK such thing is also UB in C++.
What do you think about this approach?
Assuming it is correct (which is not) I still don't like it. You want getters/setters but C++ does not support this feature. So instead of doing those weird, complicated constructs (imagine other people maintaining this code) how about simply do
struct Vector3f {
float data[3];
float x() {
return data[0];
}
void x(float value) {
data[0] = value;
}
...
};
You say this code is ugly. Maybe it is. But it is simple, easy to read and maintain. There's no UB, it does not depend on potential hacks with unions, and does exactly what you want, except for beauty requirement. :)
GLM implements this kind of functionality using anonymous structs inside an anonymous union
I can't personally guarantee that this is standard-compliant, but most major compilers (MSVC, GCC, Clang) will support this idiom:
struct Vector3f {
union {
struct {
float x, y, z;
};
struct {
float data[3];
};
};
Vector3f() : Vector3f(0,0,0) {}
Vector3f(float x, float y, float z) : x(x), y(y), z(z) {}
};
int main() {
Vector3f vec;
vec.x = 14.5;
std::cout << vec.data[0] << std::endl; //Should print 14.5
vec.y = -22.345;
std::cout << vec.data[1] << std::endl; //Should print -22.345
std::cout << sizeof(vec) << std::endl; //On most platforms will print 12
}
The non-standard behavior is in the anonymous struct used to group the letters together, which GCC will issue a warning about. As far as I know, the union itself should be valid, because the datatypes are all identical, but you should still check with your compiler documentation if you're unsure whether this is valid or not.
As an added convenience, we can also overload the brackets operator to shorten our syntax a little:
struct Vector3f {
/*...*/
float& operator[](size_t index) {return data[index];}
float operator[](size_t index) const {return data[index];}
};
int main() {
Vector3f vec;
vec.x = 14.5;
std::cout << vec[0] << std::endl; //Should print 14.5
vec.y = -22.345;
std::cout << vec[1] << std::endl; //Should print -22.345
std::cout << sizeof(vec) << std::endl; //On most platforms will print 12
}
Just for clarity, accessing inactive members in the way I am is valid according to the C++ standard, because those members share a "common subsequence":
If two union members are standard-layout types, it's well-defined to examine their common subsequence on any compiler.
CPP Reference: Union Declaration
Because x and data[0] are
Both floats,
Both occupy the same memory,
Are both standard Layout types as the standard defines them,
It's perfectly valid to access one or the other regardless of which is currently active.
As stated, this is impossible: pointer arithmetic is defined only within an array, and there’s no way (without putting a reference in the class, which takes up space in current implementations) to have v.x refer to an array element.

C++ vector class definition

I'm only beginning in C++ and I'm struggling to understand some code from a custom vector class in an article I'm working through. The author writes it as:
class vec3
{
public:
vec3() {}
vec3(float e0, float e1, float e2)
{
e[0] = e0;
e[1] = e1;
e[2] = e2;
}
(...)
But so far I've only seen class definitions where the types of data it holds are defined, such as:
class vec3
{
public:
float m_x;
float m_y;
float m_z;
vec3(float x, float y, float z) : m_x(x), m_y(y), m_z(z)
{}
My guess was that the code in the article is creating an empty vector which it then populates with floats or there was something assumed in the definition. Is this just a syntax difference or is there something more fundamental that I'm missing? Apologies for what seems like a basic question but I couldn't find any similar questions. . . it might be too basic for that! But I just wanted to understand it before I moved on.
Thanks,
Paddy
In the code you've posted, you are correct that there is no declaration for the variable e anywhere. I'm not sure if this is because you didn't post that part of the code from the book, or if the book omitted that for brevity.
Without knowing what the book author was meaning by e, I don't want to suggest a completion of the code. There are several things that e could be declared as that would be compatible with the code you've posted.
It defines e as just a float array [e[3]].
With this information added, then there is no relevant difference between three separate members and an array. In the end, both variants will require the same amount of memory, and in most cases, the (optimised!) code generated by the compiler will be exactly the same:
float getY()
{
return m_y;
// will result in address of object + offset to m_y
}
float getY()
{
return e[1];
// will result in address of object + offset to e + offset to second element
// as both offsets are constant, they will be joined to one single summand
// and we are back at first variant...
}
One of the few things you can do with arrays but not with separate members is having a loop, such as the following:
float magnitude()
{
float sum = 0.0F;
for(auto f : e)
sum += f*f;
return sqrtf(sum);
}
However, for such short loops, loop unrolling is pretty likely, and the code generated again is with high probability equivalent to the separate member variant:
float magnitude()
{
return sqrtf(m_x * m_x + m_y * m_y + m_z * m_z);
}
With an array, you could pass all three members in one single parameter to other functions (as pointer to first element), with separate members, you'd have to pass all of them separately (well, there are ways around, but they either require extra effort or are "dirty"...).

Aliasing struct and array the C++ way

This is a C++ followup for another question of mine
In the old days of pre-ISO C, the following code would have surprised nobody:
struct Point {
double x;
double y;
double z;
};
double dist(struct Point *p1, struct Point *p2) {
double d2 = 0;
double *coord1 = &p1->x;
double *coord2 = &p2->x;
int i;
for (i=0; i<3; i++) {
double d = coord2[i] - coord1[i]; // THE problem
d2 += d * d;
}
return sqrt(d2);
}
Unfortunately, this problematic line uses pointer arithmetic (p[i] being by definition *(p + i)) outside of any array which is explicitely not allowed by the standard. Draft 4659 for C++17 says in 8.7 [expr.add]:
If the expression P points to element x[i] of an array object x with n elements,
the expressions P + J and J + P (where J has the value j) point to the (possibly-hypothetical) element
x[i + j] if 0 <= i + j <= n; otherwise, the behavior is undefined.
And the (non-normative) note 86 makes it even more explicit:
An object that is not an array element is considered to belong to a single-element array for this purpose. A
pointer past the last element of an array x of n elements is considered to be equivalent to a pointer to a hypothetical element
x[n] for this purpose.
The accepted answer of the referenced question uses the fact that the C language accepts type punning through unions, but I could never find the equivalent in the C++ standard. So I assume that a union containing an anonymous struct member and an array would lead to Undefined Behaviour in C++ — they are different languages...
Question:
What could be a conformant way to iterate through members of a struct as if they were members of an array in C++? I am searching for a way in current (C++17) versions, but solutions for older versions are also welcome.
Disclaimer:
It obviously only applies to elements of same type, and padding can be detected with a simple assert as shown in that other question, so padding, alignment, and mixed types are not my problem here.
Use an constexpr array of pointer-to-member:
#include <math.h>
struct Point {
double x;
double y;
double z;
};
double dist(struct Point *p1, struct Point *p2) {
constexpr double Point::* coords[3] = {&Point::x, &Point::y, &Point::z};
double d2 = 0;
for (int i=0; i<3; i++) {
double d = p1->*coords[i] - p2->*coords[i];
d2 += d * d;
}
return sqrt(d2);
}
IMHO the easiest way is to just implement operator[]. You can make a helper array like this or just create a switch...
struct Point
{
double const& operator[] (std::size_t i) const
{
const std::array coords {&x, &y, &z};
return *coords[i];
}
double& operator[] (std::size_t i)
{
const std::array coords {&x, &y, &z};
return *coords[i];
}
double x;
double y;
double z;
};
int main()
{
Point p {1, 2, 3};
std::cout << p[2] - p[1];
return 0;
}
struct Point {
double x;
double y;
double z;
double& operator[]( std::size_t i ) {
auto self = reinterpret_cast<uintptr_t>( this );
auto v = self+i*sizeof(double);
return *reinterpret_cast<double*>(v);
}
double const& operator[]( std::size_t i ) const {
auto self = reinterpret_cast<uintptr_t>( this );
auto v = self+i*sizeof(double);
return *reinterpret_cast<double const*>(v);
}
};
this relies on there being no packing between the doubles in your `struct. Asserting that is difficult.
A POD struct is a sequence of bytes guaranteed.
A compiler should be able to compile [] down to the same instructions (or lack thereof) as a raw array access or pointer arithmetic. There may be some problems where this optimization happens "too late" for other optimzations to occur, so double-check in performance sensitive code.
It is possible that converting to char* or std::byte* insted of uintptr_t would be valid, but there is a core issue about if pointer arithmetic is permitted in this case.
You could use the fact that casting a pointer to intptr_t doing arithmetic and then casting the value back to the pointer type is implemetation defined behavior. I believe it will work on most of the compilers:
template<class T>
T* increment_pointer(T* a){
return reinterpret_cast<T*>(reinterpret_cast<intptr_t>(a)+sizeof(T));
}
This technic is the most efficient, optimizers seems not to be able to produce optimal if one use table look up: assemblies-comparison

What is the advantage of using union for struct and array of same size

I read somewhere a piece of code for defining 3d coordinate. So, they used x, y & z coordinate like this below:
union
{
struct
{
float x, y, z;
};
float _v[3];
};
My question is that why a union is required here and also what is the advantage of using struct with an array?
Important note: this construct leads to undefined behavior. What follows is a description of its authors' intentions, which, unfortunately, many compilers translate to precisely the behavior the authors expect, which in turn leads to proliferation of code like that.
union construct is not really required here: the authors used it for convenience. The reason they put a union there is to give themselves a syntax for accessing x, y, and z in two distinct ways:
By specifying the field name - that is, coord.x, coord.y, or coord.z, or
By specifying the field index - that is, coord._v[0], coord._v[1], or coord._v[2].
An approach that provides comparable functionality without running into undefined behavior is to use inline member functions for your access:
struct Vector3D {
int v[3];
int& x() { return v[0]; }
int& y() { return v[1]; }
int& z() { return v[2]; }
};
int main() {
Vector3D coord;
coord.v[0] = 5;
cout << coord.x() << endl;
coord.y() = 10;
cout << coord.v[1] << endl;
return 0;
}
Demo.
As Gill Bates says, in this way you can (maybe) access the 3 coordinates both as x, y, z and as v[0], v[1], v[2]
But as per #Richard Critten comment, this is actually an UB.
You can get the same result in a "safe" way with something like this:
struct Coordinates
{
Coordinates():x(v[0]), y(v[1]), z(v[2])
{
}
int v[3];
int& x;
int& y;
int& z;
};
i.e., using references to the array values and initializing them in constructor
Size of this struct will be obviously different (larger) than the union you show in OP
This way you can address the 3d coordinate as a struct..
foo.x;
foo.y; // etc
But it also allows you to get the 3 variables as an array while occupying the same space (that's the plan at least), accessing them like..
foo._v[0] // x, etc
Anyway, that's the idea. But the moment the struct has any sort of padding between members your array will be misaligned and you will end up reading garbage values. Long story short, this code has undefined behaviour, a bad implementation that shouldn't be used.