#include<iostream>
#include<conio.h>
class Number
{
private:
int x, y;
public:
Number()
{
x = y = 100;
}
void avg()
{
std::cout<<"x = "<<std::cout<<x;
std::cout<<std::endl;
std::cout<<"Y = "<<std::cout<<y;
std::cout<<std::endl;
std::cout<<"Average = "<<std::cout<<(x+y)/2;
}
};
main()
{
Number n;
n.avg();
}
This programme runs but shows wrong answer, may be showing addresses of memory locations instead of showing the assigned values of 100. Please correct me why it is behaving like this?
std::cout << "x = " << std::cout << x;
is wrong. You need
std::cout << "x = " << x;
Otherwise, the std::cout stream object in ...<< std::cout is implicitly converted to a (void*) when invoking operator<< on it, and therefore the pointer (an address) is displayed.
The conversion to void* exists for historic reasons (the safe bool idiom), but in C++11 was removed, due to the introduction of explicit conversion operators, so your code should not compile in C++11.
Related
I did the following as a cheap way to allow read-only access to a member container _numbers via numbers:
class Foo {
Foo() : _numbers({}), numbers(_numbers) {
// some code that populates `numbers` via `numbers.push_back(...)`
}
private:
std::vector<int> _numbers;
public:
const std::vector<int>& numbers;
}
However, doing so I see that numbers is empty, while in other cases it will contain the same elements as _numbers.
To be more precise, it seems to be undefined behavior.
In my real example (of which this a simplified version) I have multiple reference-container pairs with this scheme, where the populated data is visible in the const-reference member for some pairs, and for some it is not.
Any idea whats wrong with this? Any help is deeply appreciated.
EDIT Here is a minimal working example:
#include <vector>
struct Foo2 {
public:
const int max1;
const int center1;
Foo2(const int max1_);
private:
std::vector<int> _numbers1, _numbers2;
public:
const std::vector<int>& numbers1, numbers2;
};
Foo2::Foo2(const int max1_)
: max1(max1_), center1(max1_/2),
_numbers1({}), _numbers2({}),
numbers1(_numbers1),
numbers2(_numbers2)
{
cout << max1 << endl;
for (int i=0; i<center1; i++) {
_numbers1.push_back(i);
cout << "A: " << i << endl;
}
for (int i=center1; i<max1; i++) {
_numbers2.push_back(i);
cout << "B: " << i << endl;
}
for (int i: numbers1) {
cout << "A: " << i << endl;
}
for (int i: numbers2) {
cout << "B: " << i << endl;
}
}
which gives the following Output when initializing Foo2 f(8):
8
A: 0
A: 1
A: 2
A: 3
B: 4
B: 5
B: 6
B: 7
A: 0
A: 1
A: 2
A: 3
i.e. numbers2 does not see the contents of _numbers2 while for numbers1 it seems to work.
const vector<int>& numbers1, numbers2; — Here, only the first variable is a reference. You need & before the second variable to make it a reference as well. Then the code should work.
But I have to say that what you're doing is a really bad idea. You're paying for a convenient syntax with memory overhead, non-assignability, and possibly speed overhead.
Use getters instead: const vector<int>& numbers1() const {return _numbers1;}. Yes, you will have to type the extra () every time.
Hmm... The main cause of the problem was given by #HolyBlackCat: numbers2 was not a reference but an independant copy.
But IMHO there is a more fundamental problem. With:
public:
const std::vector<int>& numbers;
You promise the compiler, that once initialized, the vector referenced by numbers will no longer change. Which is a lie, because the underlying vector changes...
Lying to the compiler is a sure path to UB: it will work sometimes, and will suddenly break because the compiler is free to change its actual code so that no changes to _member will be reflected in members.
Possible fixes:
use std::vector<int>& numbers = _numbers; (no const). This one will be fine, but you loose the ability to present a read only reference
get a fully initialized reference when you need it through a getter (i.e. a method):
const std::vector& numbers() {
return _numbers;
}
Again it is fine, provided _number no longer changes after complete initialization of Foo
use a dedicated object, implicitely convertible to a vector that will be fully initialized before being used:
struct Bar {
std::vector<int>_numbers;
Bar(bool first) : Bar(0, first) {};
Bar(int max, bool first) {
cout << max << endl;
int center = max / 2;
if (first) {
for (int i = 0; i < center; i++) {
_numbers.push_back(i);
cout << "A: " << i << endl;
}
}
else {
for (int i = center; i < max; i++) {
_numbers.push_back(i);
cout << "B: " << i << endl;
}
}
}
operator const std::vector<int>& () {
return _numbers;
}
};
struct Foo2 {
public:
const int max1;
const int center1;
Foo2();
Foo2(const int max1_);
private:
Bar _numbers1, _numbers2;
public:
const std::vector<int>& numbers1, &numbers2;
};
I'm trying to implement a simple vector-swizzling functionality as a pet project to get into template metaprogramming. With the help of open-source mathematics library glm and some other posts on SO, I have come up with a solution which is basically working but has one error.
I have implemenented several structs which hold the data I need to represent a two dimensional eucledian vector. The struct "vec2" has a union which holds a float array with two elements (float data[2]) and two instances of struct "scalarSwizzle" which is supposed to implement the swizzling mechanic which allows me to acces the vector like so vec.data[0] or so vec.x.
Following the code I implemented so far:
#include <iostream>
template<typename T>
void print(T value)
{
std::cout << "print func: " << value << std::endl;
}
template<typename T, unsigned int I>
struct scalarSwiz
{
T value[1];
T &operator=(const T newValue)
{
value[I] = newValue;
return value[I];
}
operator T()
{
return value[I];
}
};
template<typename T>
struct vec2
{
union
{
T data[2];
scalarSwiz<T, 0> x;
scalarSwiz<T, 1> y;
};
vec2()
{
x = 0.0f;
y = 1.0f;
}
vec2(T pA, T pB)
{
x = pA;
y = pB;
}
};
int main(int argc, char *args[])
{
vec2<float> vec1{5.0f, 1.0f};
std::cout << "value vec1.data[0]: " << vec1.data[0] << std::endl;
std::cout << "value vec1.data[1]: " << vec1.data[1] << std::endl;
std::cout << "value vec1.x: " << vec1.x << std::endl;
std::cout << "value vec1.y: " << vec1.y << std::endl << std::endl;
print(vec1.data[0]);
print(vec1.data[1]);
print(vec1.x);
print(vec1.y);
std::cin.get();
}
The output is the following:
value vec1.data[0]: 5
value vec1.data[1]: 567.4
value vec1.x: 5
value vec1.y: 567.4
print func: 5
print func: 567.4
print func: 5
print func: 2.5565e-39
I expected the output to be the same for both printing the values directly in main() and via print() but vec.y is not resolved when I print it via the print() function. So I guess something is wrong with the overloaded typecast operator in "scalarSwizzle" but i have no idea what.
What I also dont understand is, why visual studio also doesn't resolve the value properly as seen on the following image:
vec1.y seem to be pointing to the same physical address then vec.x, while the direct std::cout in main() works fine.
I've been trying for a couple of days now to wrap my head around the problem, why the overloaded typecast operator doesnt work for vec.y but i just dont get it. Maybe someone here can help my with this problem.
Thank you!
First of all
template<typename T, unsigned int I>
struct scalarSwiz
{
T value[1];
T &operator=(const T newValue)
{
value[I] = newValue;
return value[I];
}
operator T()
{
return value[I];
}
};
results in undefined behavior if I != 0 (array access out of bounds) so don't expect your code to be correct or even stable.
Secondly, accessing an inactive member of a union is also undefined behavior (as per c++ standard). However, msvc, gcc and clang extend the c++ standard so that accessing inactive member behaves like we expect it to.
And finally, your scalarSwiz type can be replaced by an anonymous struct:
template<typename T>
struct vec2
{
union
{
T data[2];
struct
{
T x, y;
};
};
vec2()
{
x = 0.0f;
y = 1.0f;
}
vec2(T pA, T pB)
{
x = pA;
y = pB;
}
};
In regards to your Visual Studio debugger display: this is because of your scalarSwiz definition. You define an array of length 1 T value[1] and you put 2 scalarSwiz objects in a union. Because every member of a union share the same memory (or rather start at the same memory location), both of your value members point to the beginning of the data array. The watch window only displays the members and their values of a certain type, it has no knowledge of your quirky indexing. And because both arrays occupie the same memory, the same value is shown.
I updated my code regarding Timo's answer:
#include <iostream>
template<typename T>
void print(T value)
{
std::cout << "print func: " << value << std::endl;
}
template<typename T>
struct vec2
{
union
{
T data[2];
struct
{
T x, y;
};
};
vec2()
{
x = 0.0f;
y = 1.0f;
}
vec2(T pA, T pB)
{
x = pA;
y = pB;
}
};
int main(int argc, char *args[])
{
vec2<float> vec1{5.0f, 1.0f};
std::cout << "value vec1.data[0]: " << vec1.data[0] << std::endl;
std::cout << "value vec1.data[1]: " << vec1.data[1] << std::endl;
std::cout << "value vec1.x: " << vec1.x << std::endl;
std::cout << "value vec1.y: " << vec1.y << std::endl << std::endl;
print(vec1.data[0]);
print(vec1.data[1]);
print(vec1.x);
print(vec1.y);
std::cin.get();
}
I'm trying to use boost to create a multidimensional array and I want said array to be a member of some class.
However I find two problems with it:
1 - I need to declare the size of the array with
boost::extents[2][2]
Everytime I want to use the array. Otherwise I get the following error:
a.out: /usr/include/boost/multi_array/base.hpp:136: Referenceboost::detail::multi_array::value_accessor_n<T, NumDims>::access(boost::type<Reference>, boost::detail::multi_array::value_accessor_n<T, NumDims>::index, TPtr, const size_type*, const index*, const index*) const [with Reference = boost::detail::multi_array::sub_array<double, 1ul>; TPtr = double*; T = double; long unsigned int NumDims = 2ul; boost::detail::multi_array::value_accessor_n<T, NumDims>::index = long int; boost::detail::multi_array::multi_array_base::size_type = long unsigned int]: Assertion `size_type(idx - index_bases[0]) < extents[0]' failed.
2 - Ok, maybe this is just part of how multidimensional arrays work in C++ with Boost, I'm going to write my code accepting every function "declares" the array. However, if I do this I find the array is empty.
Here's a snippet of code that reproduces this problem. During the "construction" of the class the array should be filled. However, the line
cout << "Result: " << testing.getArrayMember(0,1) << endl;
outputs "Result: 0".
#include <iostream>
#include "boost/multi_array.hpp"
typedef boost::multi_array<double, 2> dbl_array;
using namespace std;
class TestClass {
public:
dbl_array darray;
TestClass(double x);
void fillArray(double x);
double getArrayMember(int i, int j);
};
TestClass::TestClass(double x) {
dbl_array darray(boost::extents[2][2]);
cout << "Class constructor called" << endl;
fillArray(x);
}
void TestClass::fillArray(double x) {
cout << "Filling array" << endl;
dbl_array darray(boost::extents[2][2]); // Without this line, the code fails at runtime
darray[0][0] = x;
darray[1][0] = 2.0*x;
darray[0][1] = 3.0*x;
darray[1][1] = 4.0*x;
cout << "Array filled" << endl;
}
double TestClass::getArrayMember(int i, int j) {
dbl_array darray(boost::extents[2][2]); // Without this line, the code fails at runtime
return darray[i][j];
}
int main() {
TestClass testing = TestClass(5.0);
// The result is 0 in the end
cout << "Result: " << testing.getArrayMember(0,1) << endl;
return 0;
}
What am I doing wrong here?
Option 1 is to use an initialisation list:
TestClass::TestClass(double x) : darray(boost::extents[2][2]) {
cout << "Class constructor called" << endl;
fillArray(x);
}
Since otherwise the member of the class darray is created using the default constructor and not through your line
dbl_array darray(boost::extents[2][2]);
as you believe.
This is the same answers as given in initialize boost::multi_array in a class
However, I want to add the following bit, which I think it is relevant in this situation:
It might be necessary for you to generate the array after performing some kind of operation in the constructor of your class. You can achieve this using "resize" after the array has been created by the default constructor.
Ie, instead of
TestClass::TestClass(double x) {
dbl_array darray(boost::extents[2][2]);
cout << "Class constructor called" << endl;
fillArray(x);
}
you could have
TestClass::TestClass(double x) {
darray.resize(boost::extents[2][2]);
cout << "Class constructor called" << endl;
fillArray(x);
}
This question already has answers here:
Uninitialized values being initialized?
(7 answers)
Closed 8 years ago.
I'm doing some testing...
Firstly I post my source code
the .h file
class Complex{
private:
int r = 0;//initializer
int i ;
public:
Complex(int , int I = 0);
Complex();
void print();
void set(int, int I = 1);
static void print_count();
static int count;
};
the .cpp file
#include <iostream>
#include "complex.h"
int Complex::count = 1;
Complex::Complex(int R , int I){
r = R;
i = I;
count++;
std::cout << "constructing Complex object...count is " << Complex::count << std::endl;
}
Complex::Complex(){//default constructor
std::cout << "default constructor is called..." << std::endl;
}
void Complex::print(){
std::cout << "r = " << r << ';' << "i = " << i << std::endl;
return;
}
void Complex::set(int R, int I /*= 2*/){//will be "redefaulting", an error
r = R;
i = I;
return;
}
void Complex::print_count(){//static
Complex::count = -1;//jsut for signaling...
std::cout << "count is " << count << std::endl;
return;
}
the main function
#include <iostream>
#include "complex.h"
int main(){
Complex d;//using default constructor
d.print();
/*Complex c(4, 5);*/
Complex c(4);
//c.print();
/*c.set(2, 3)*/
c.print();
c.set(2 );
c.print();
std::cout << "count is " << c.count << std::endl;//c can access member data
c.print_count();
c.count++;//
return 0;
}
consider the Complex object d constructed with default ctor
because the data member r is initialized using with 0, when executing d.print(),
r is expected to be 0
and i isn't, so I expected it to be garbage value
but when I'm testing, one strange thing happens.
if I eliminate this and the following lines of code in the main file:
std::cout << "count is " << c.count << std::endl;//c can access member data
then d.print() will give the value of i as 32767 on my system, which I guess it's a garbage value;
but once that line is added, d.print() just give i's value to 0 on my system.
I don't get it. I hasn't set, modiify or initialize i's value, why should it be 0?
or, it is also a garbage value?
or, calling one of those function corrupts the value of i?
how is the thing run behind the scene here?
thx for helping.
0 is just as garbage value as any other. Don't make the mistake of thinking otherwise.
Formally, reading an uninitialized variable is undefined behavior, so there's no point in wondering about it: just fix it by initializing the variable properly.
I was debugging some code involving pointers to member fields, and i decided to print them out to see their values. I had a function returning a pointer to member:
#include <stdio.h>
struct test {int x, y, z;};
typedef int test::*ptr_to_member;
ptr_to_member select(int what)
{
switch (what) {
case 0: return &test::x;
case 1: return &test::y;
case 2: return &test::z;
default: return NULL;
}
}
I tried using cout:
#include <iostream>
int main()
{
std::cout << select(0) << " and " << select(3) << '\n';
}
I got 1 and 0. I thought the numbers indicated the position of the field inside the struct (that is, 1 is y and 0 is x), but no, the printed value is actually 1 for non-null pointer and 0 for null pointer. I guess this is a standard-compliant behavior (even though it's not helpful) - am i right? In addition, is it possible for a compliant c++ implementation to print always 0 for pointers-to-members? Or even an empty string?
And, finally, how can i print a pointer-to-member in a meaningful manner? I came up with two ugly ways:
printf("%d and %d\n", select(0), select(3)); // not 64-bit-compatible, i guess?
ptr_to_member temp1 = select(0); // have to declare temporary variables
ptr_to_member temp2 = select(3);
std::cout << *(int*)&temp1 << " and " << *(int*)&temp2 << '\n'; // UGLY!
Any better ways?
Pointers to members are not as simple as you may think. Their size changes from compiler to compiler and from class to class depending on whether the class has virtual methods or not and whether it has multiple inheritance or not. Assuming they are int sized is not the right way to go. What you can do is print them in hexadecimal:
void dumpByte(char i_byte)
{
std::cout << std::hex << static_cast<int>((i_byte & 0xf0) >> 4);
std::cout << std::hex << static_cast<int>(i_byte & 0x0f));
} // ()
template <typename T>
void dumpStuff(T* i_pStuff)
{
const char* pStuff = reinterpret_cast<const char*>(i_pStuff);
size_t size = sizeof(T);
while (size)
{
dumpByte(*pStuff);
++pStuff;
--size;
} // while
} // ()
However, I'm not sure how useful that information will be to you since you don't know what is the structure of the pointers and what each byte (or several bytes) mean.
Member pointers aren't ordinary pointers. The overloads you expect for << aren't in fact there.
If you don't mind some type punning, you can hack something up to print the actual values:
int main()
{
ptr_to_member a = select(0), b = select(1);
std::cout << *reinterpret_cast<uint32_t*>(&a) << " and "
<< *reinterpret_cast<uint32_t*>(&b) << " and "
<< sizeof(ptr_to_member) << '\n';
}
You can display the raw values of these pointer-to-members as follows:
#include <iostream>
struct test {int x, y, z;};
typedef int test::*ptr_to_member;
ptr_to_member select(int what)
{
switch (what) {
case 0: return &test::x;
case 1: return &test::y;
case 2: return &test::z;
default: return NULL;
}
}
int main()
{
ptr_to_member x = select(0) ;
ptr_to_member y = select(1) ;
ptr_to_member z = select(2) ;
std::cout << *(void**)&x << ", " << *(void**)&y << ", " << *(void**)&z << std::endl ;
}
You get warnings about breaking strict anti-aliasing rules (see this link), but the result is what you might expect:
0, 0x4, 0x8
Nevertheless, the compiler is free to implement pointer-to-member functionality however it likes, so you can't rely on these values being meaningful.
I think you should use printf to solve this problen
#include <stdio.h>
struct test{int x,y,z;}
int main(int argc, char* argv[])
{
printf("&test::x=%p\n", &test::x);
printf("&test::y=%p\n", &test::y);
printf("&test::z=%p\n", &test::z);
return 0;
}