This question already has answers here:
Can a local variable's memory be accessed outside its scope?
(20 answers)
Closed 7 years ago.
I'm trying to learn C++ and had a question about returning arrays in C++. I know that in this case perhaps Vector may be better and that there is no need for a getter method as the fields are visible within the same class but I'm trying to learn about memory management so I'll use them.
class Color {
double r;
double g;
double b;
public:
Color(int a, int aa, int aaa) {
r = a;
g = aa;
b = aaa;
}
bool operator==(const Color &other) {
double *otherCol = other.getter();
return otherCol[0] == r && otherCol[1] == g && otherCol[2] == b;
}
double* getter() const {
double second[3] = {r,g,b};
return second;
}
};
int main() {
Color col1(23, 54, 200);
Color col2(23, 54, 200);
cout << (col1 == col2) << endl;
return 0;
}
This code should print out a 1 if the RGB colors are the same and 0 otherwise. But it does not print a 1. To debug, I added the following lines (twice on purpose) right before the return statement in operator==:
cout << otherCol[0] << " " << otherCol[1] << " " << otherCol[2] << endl;
cout << otherCol[0] << " " << otherCol[1] << " " << otherCol[2] << endl;
Oddly enough, the results are different:
23 54 200
6.91368e-310 6.91368e-310 3.11046e-317
Can someone please tell me what causes this and what would be a reasonable remedy that does not rely on Vector or dynamic allocation of memory? Let's assume that we don't want to pass in an array into getter() to update.
In getter you are returning the address of a local variable which results in undefined behavior so you are getting random memory. If you return a pointer you have to do something like new the variable in the called function and delete it after the function returns.
Or you could make second a class member which would keep it from going out of scope.
You could also pass the array in as a parameter.
Related
#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.
This question already has an answer here:
Error in Getting Value from Vector of Pairs
(1 answer)
Closed 7 years ago.
I am having trouble with printing values from my struct Pages. I am trying to print the value of segment in Pages from a list of pages. The assignSegments() method is assigning values to the variable segment. This is the error I am getting. ‘std::list::iterator’ has no member named ‘segment’
Here is the code I have so far. If you need more code from me just let me know.
Following code is in my main
Process child;
char c = 'A';
c = c+i;
child.letter = c;
assignSegments(child.childPages, child.letter, CreateRandomNumber());
for(list<Pages>::iterator iter = child.childPages.begin(); iter != child.childPages.end(); i++)
{
cout << *iter.segment << endl; // having trouble printing here
}
Here are my structs that I am using.
struct Pages
{
string segment;
char validBit;
int refByte;
Pages * pagePointer;
int* memoryPointer;
};
struct Process
{
char letter;
list<Pages> childPages;
};
I think cout << iter->segment << endl; is what you're looking for.
operator. has a higher precedence over operator*, so iter.segment will be evaluated first, obviously it's not what you want.
Reference for C++ Operator Precedence
you can change
cout << *iter.segment << endl;
to
cout << (*iter).segment << endl;
or just
cout << iter->segment << endl;
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.
This question already has answers here:
Can a local variable's memory be accessed outside its scope?
(20 answers)
Closed 9 years ago.
The printResults() method below (called from the main method at the bottom) returns -858993460 for all four values. Why is this? I have confirmed with cout statements that the numbers and calculations are correct within the doCalc() method, so I'm assuming the error is in the way I'm using pointers and calling the printResults() method...
typedef int matrix[2][2] ;
struct matrices {
matrix a;
matrix b;
};
...getInput() method constructs
matrix* doCalc (matrices m){
matrix toReturn;
char input;
cout << "Which calculation would you like to perform - (M)ultiply, (A)dd, (S)ubtract?";
cin >> input;
switch(input){
case 'M':
toReturn[0][0] = ((m.a[0][0])*(m.b[0][0]));
cout << "XX " << ((m.a[0][0])*(m.b[0][0]));
toReturn[0][1] = (m.a[0][1]*m.b[0][1]);
cout << "YY " << (m.a[0][1]*m.b[0][1]);
toReturn[1][0] = (m.a[1][0]*m.b[1][0]);
toReturn[1][1] = (m.a[1][1]*m.b[1][1]);
break;
case 'A':
toReturn[0][0] = (m.a[0][0]+m.b[0][0]);
toReturn[0][1] = (m.a[0][1]+m.b[0][1]);
toReturn[1][0] = (m.a[1][0]+m.b[1][0]);
toReturn[1][1] = (m.a[1][1]+m.b[1][1]);
break;
case 'S':
toReturn[0][0] = (m.a[0][0]-m.b[0][0]);
toReturn[0][1] = (m.a[0][1]-m.b[0][1]);
toReturn[1][0] = (m.a[1][0]-m.b[1][0]);
toReturn[1][1] = (m.a[1][1]-m.b[1][1]);
break;
}
return &toReturn;
}
void printResult(matrix m){
cout<<"---RESULT---\n";
cout << m[0][0] << " " << m[0][1] << "\n";
cout << m[1][0] << " " << m[1][1] << "\n";
}
void main() {
matrices m = getInput();
cout << m.a[0][0] << " " << m.a[0][1] << "\n";
cout << m.a[1][0] << " " << m.a[1][1] << "\n\n";
cout << m.b[0][0] << " " << m.b[0][1] << "\n";
cout << m.b[1][0] << " " << m.b[1][1] << "\n";
matrix* calc = doCalc(m);
matrix c = &calc;
printResult(*calc);
}
the matrix toReturn will be destroyed when the function exits, you will need to use some form of persistent memory allocation (look up new and delete). As such all the values are just nonsense.
matrix toReturn; is a local variable, allocated on the stack. After doCalc returns, its contents are undefined. In this case, the memory at its old address gets overwritten with random garbage.
toReturn will be destroyed with the stack frame when doCalc is finished.
Instead of returning the pointer pass it to the function you are calling.
void doCalc (matrices m, matrix* pReturnMatrix)
matrix* calc = new matrix();
doCalc(m, calc);
toReturn is a local variable in the doCalc function. It will no longer exist when the function returns.
An easy way to fix this is to pass a reference to the matrix that will store the result:
matrix* doCalc (matrices m, matrix& toReturn ){
Then remove this line from doCalc:
matrix toReturn;
And change how the function is called from this:
matrix* calc = doCalc(m);
matrix* calc = doCalc(m);
matrix c = &calc;
printResult(*calc);
To this:
matrix calc;
doCalc(m,calc);
printResult(calc);
There are other ways to fix this, e.g. new/delete as suggested in other places. However, now we will go into who allocates and who owns the memory. It won't be clear from the function signature alone who is responsible for what.
You can avoid managing dynamically allocated memory and requiring the caller supply an lvalue if you return by value.
matrix doCalc (const matrices& m)
{
matrix toReturn;
// Code here
return toReturn;
}
You can assign the results to a matrix object or use it in an expression like below.
if(doCalc(m).a[0][0] == 1)
{
// do something
}
or
matrix mat(doCalc(m));
if(mat.a[0][0] == 1)
{
// do something
}
This question already has answers here:
Function argument type followed by *&
(3 answers)
Closed 9 years ago.
I was looking at manual of ACE framework and came across this declaration
int ACE_Stream<>::get (ACE_Message_Block *& mb, ACE_Time_Value * timeout = 0)
I'm not able to understand what *& stands for. I know * is for pointer and & is reference. Can any one explain what is the meaning of this declaration.
Thanks in advance
So as #NPE said *& makes changes to pointer propagate back. But to understand I just wrote down some code sharing it so that it can help others understand this correctly
#include <iostream>
using namespace std;
class DoSomething
{
public:
int n;
DoSomething(int i){
n = i;
}
virtual ~DoSomething();
};
DoSomething::~DoSomething()
{
}
int dosomething(DoSomething * a)
{
cout << "Got value from caller: (in dosomething) = " << a << endl;
a = new DoSomething(25);
return 0;
}
int dosomethingElse(DoSomething *& a)
{
cout << "Got value from caller: (in dosomethingElse) = " << a << endl;
a = new DoSomething(15);
return 0;
}
int main(int argc, char *argv[])
{
DoSomething *d = new DoSomething(10);
cout << "Pointer to DoSomething: " << d << endl;
dosomething(d);
cout << "After dosomething value of d: " << d << endl << endl;
dosomethingElse(d);
cout << "After dosomethingElse value of d: " << d << endl << endl;
delete d;
return 0;
}
So as #NPE said here is out put of this
Pointer to DoSomething: 0x955f008
Got value from caller: (in dosomething) = 0x955f008
After dosomething value of d: 0x955f008
Got value from caller: (in dosomethingElse) = 0x955f008
After dosomethingElse value of d: 0x955f028
So indeed if I create a new instance inside function it will propagate only if I use *& and not just *
Thank you to every one for the answers.
I know * is for pointer and & is reference.
Correct. So what you have here is a pointer, passed by reference.
mb is a pointer that's being passed by reference. This means that if get() were to change the value of the pointer, the change would propagate back to the caller.