Modify pointer inside class - c++

I'm having a trouble manipulating a pointer inside a class.
#include <iostream>
using namespace std;
class myClass {
public:
void modifyPointer(float *pointer);
};
void myClass::modifyPointer(float *pointer) {
pointer = new float[3];
pointer[0] = 0;
pointer[1] = 1;
pointer[2] = 2;
cout << "Address: " << pointer << endl;
}
int main()
{
float* pointer;
myClass object;
object.modifyPointer(pointer);
cout << "Address: " << pointer << endl;
cout << "Values: " << pointer[0] << "," << pointer[1] << "," << pointer[2]
<< std::endl;
return 0;
}
When I print the pointer inside the class I get its address, but in the main program I get a 0 address and a seg fault when printing values. What am I wrong in how to modify this pointer?

You are taking the pointer by copy, so you don't see the changes in main. You need to take the pointer by reference, like this:
void myClass::modifyPointer(float * &pointer) {
pointer = new float[3];
// ...
}
You have to change the declaration of this function as well, of course.
Here's a working demo.

Pointers are just like any other objects. Passing an object as an argument by value creates a copy of that object. This means the original pointer in main() remains unaffected. And since it is unaffected and not initialized, accessing an array out of bounds with pointer[any_index] results in undefined behavior. Pass by reference instead:
void modifyPointer(float*& pointer)

Related

Why C++ erase params of object accessed by reference from other object also accessed by reference? [duplicate]

This question already has answers here:
C++ dangling reference strange behaviour
(5 answers)
What is a dangling reference? [duplicate]
(1 answer)
Closed last month.
I am relatively new in C++ and didn't expect the behavior shown in code below.
Can you, please, advise why is it happening and how to fix it?
DataWrapper.h
#pragma once
class DataWrapper
{
public:
int myVal;
DataWrapper();
};
DataWrapper.cpp
#include "DataWrapper.h"
DataWrapper::DataWrapper()
{
myVal = 1;
}
DataCaller.h
#pragma once
#include "DataWrapper.h"
class DataCaller
{
public:
DataWrapper* dwRef;
DataCaller();
void PrintData();
};
DataCaller.cpp
#include "DataCaller.h"
#include <iostream>
DataCaller::DataCaller()
{
dwRef = &DataWrapper();
int extractedVal = dwRef->myVal;
int dwAddr = (int)dwRef;
std::cout << "Val In DataCaller Constructor: "<< extractedVal << " dwAddr: " << dwAddr << std::endl;
}
void DataCaller::PrintData()
{
int extractedVal = dwRef->myVal;
int dwAddr = (int)dwRef;
std::cout << "Val In DataCaller PrintData: " << extractedVal << " dwAddr: " << dwAddr << std::endl;
}
Main.cpp
#include <post-processing/DataCaller.h>
int main(int argc, char* argv[])
{
DataCaller dc = DataCaller();
dc.PrintData();
return 0;
}
So I fill the value in DataWrapper constructor , in DataCaller constructor I create DataWrapper pointer, then print DataWrapper pointer's value.
I also print this value in regular method of DataCaller class.
When I print it in constructor, it is equal to 1, as written in DataWrapper constructor, but when I print it in DataCaller method - the value is set to rubbish.
At the same time "dwAddr" is the same in both cases.
Here is an example of my output:
Val In DataCaller Constructor: 1 dwAddr: 2035349268
Val In DataCaller PrintData: -858993460 dwAddr: 2035349268
Can you, please, advise why is it happening and how to fix it?
As explained by #RichartCritten in the comment, the object created via DataWrapper() is destroyed at the end of the expression
dwRef = &DataWrapper();
which results in undefined behaviour.
If you want to keep the object, one alternative is to make dwRef a non-pointer member variable.
class DataCaller
{
public:
DataWrapper dwRef;
DataCaller();
void PrintData();
};
...
DataCaller::DataCaller()
: dwRef(/* constructor parameters could be listed here */)
{
...
}
Alternatively allocate the object via new; It's preferrable to have a smart pointer manage the calls to new and delete though:
...
#include <memory>
...
class DataCaller
{
public:
std::unique_ptr<DataWrapper> dwRef;
DataCaller();
void PrintData();
};
...
DataCaller::DataCaller()
{
dwRef = std::make_unique<DataWrapper>(/* constructor parameters could be listed here */);
...
}
Note: To print the address via a std::ostream, it's preferrable to cast to void*; this results in a implementation defined output of the address, but usually it's an output format that works well for addresses:
// assuming the second alternative I presented is used
std::cout << "Val In DataCaller PrintData: " << extractedVal << " dwAddr: " << static_cast<void*>(dwRef.get()) << std::endl;

Why does an object still exist after std::move function?

I have a question regarding std::move function. Please refer to the code below:
#include <iostream>
#include <memory>
using namespace std;
class CPointer {
public:
CPointer(double a, double b)
{
m_dX = a;
m_dY = b;
}
~CPointer()
{
m_dX = m_dY = 0;
}
double getX() const
{return m_dX;}
double getY() const
{return m_dY;}
private:
double m_dX;
double m_dY;
};
class CContainer
{
public:
CContainer(CPointer* p)
{
m_p = p;
}
~CContainer()
{
m_p = nullptr;
}
CPointer* getP() const
{return m_p;}
private:
CPointer* m_p;
};
class CBigContainer
{
public:
CBigContainer(CContainer* p)
{
m_p = p;
}
~CBigContainer()
{
m_p = nullptr;
}
CContainer* getP() const
{return m_p;}
private:
CContainer* m_p;
};
int main()
{
CPointer* pPointer = new CPointer(150,360);
cout << "1.) " << pPointer->getX() << " , " << pPointer->getY() << "\n";
std::shared_ptr<CContainer> spContainer = std::make_shared<CContainer>(pPointer);
cout << "2.) " << pPointer->getX() << " , " << pPointer->getY() << "\n";
std::shared_ptr<CBigContainer> spBigContainer = std::make_shared<CBigContainer>(std::move(spContainer.get())); //<--- std::move here
cout << "3.) " << spBigContainer->getP()->getP()->getX() << " , " << spBigContainer->getP()->getP()->getY() << "\n";
cout << "4.) " << spContainer->getP()->getX() << " , " << spContainer->getP()->getY() << "\n";
cout << "5.) " << pPointer->getX() << " , " << pPointer->getY() << "\n";
return 0;
}
And this is the result :
My question is , I am using a std::move
std::shared_ptr<CBigContainer> spBigContainer = std::make_shared<CBigContainer>(std::move(spContainer.get()));
So I am expecting the spContainer cannot be used after the line of code, because the object inside smart pointer is removed.
But it still work fine. It seems like has no different with not using std::move in this case.
Can you explain to me in details ?
Thank you very much.
So I am expecting the spContainer cannot be used after the line of code, because the object inside smart pointer is removed.
Your code never actually requests any move operations. The smart pointers are a red herring, you could see the same behaviour in this case:
CContainer a(pPointer);
CBigContainer b( std::move(&a) );
The last line is the same as CBigContainer b( &a ); because the constructor of CBigContainer accepts a pointer, and the behaviour of move operations for primitive types (which includes pointers) is to leave the source unchanged.
Your code makes the CBigContainer object point to the CContainer object (the latter still being managed by a smart pointer). Which is a bad idea because if you then release the CContainer smart pointer, then the CBigContainer's pointer to it will dangle.
Your CContainer and CBigContainer objects hold raw pointers to other objects. Putting those objects in smart pointers doesn't change that.
In case you are unclear, these are two different things:
Move out of a smart pointer.
Move out of the object managed by a smart pointer.
The first one will leave the smart pointer empty. The second one leaves the smart pointer active and managing an object which is in a post-move state .
Here's an example of code that will move out of the spContainer:
std::shared_ptr<CContainer> other = std::move(spContainer);
This invokes a move operation because the shared_ptr on the left has a move-constructor
which accepts another shared_ptr of the same type as argument.

Accessing the members of a struct referenced by a void pointer

I've got a function that takes a void pointer as a parameter. I want to pass this function a pointer to a struct, and then access the values of that struct within the function.
//the struct
struct s{
int val;
};
//the function tries to access the object
int callback(void* p_obj)
{
//try creating a new struct based on p_obj
s2 = *(struct s*)p_obj;
std::cout << "VALUE IN CALLBACK: ";
std::cout << s2.val << std::endl; //prints a big-ass int
return 0;
}
//main calls the function
int main()
{
s s1;
s1.val = 42;
void* p1 = &s;
//show some output
std::cout << "s1.val: ";
std:cout << s1.val << std::endl; //prints 42
//std::cout << "p1->val: ";
//std:cout << *(struct s*)p1->val << std::endl; //does not compile
s p2 = *(struct s*)p1;
std::cout << "p2.val: ";
std:cout << p2.val << std::endl; //prints 42
//call the function
callback(&p1);
return 0;
}
I would expect the output in the callback function to be
VALUE IN CALLBACK: 42
VALUE IN CALLBACK: 42
but, instead, I think it's printing a memory address
VALUE IN CALLBACK:1989685088
VALUE IN CALLBACK:1989685088
Trying to access the members of a void pointer directly results in an error.
int callback(void* p_obj)
{
std::cout << "VALUE IN CALLBACK: ";
std::cout << (struct s*)p_obj->val << std::endl;
}
error: 'void*' is not a pointer-to-object type
Why is this? How can I access the members of a struct that a void* is pointing to?
EDIT: Fixed some typos in the writeup
You have two errors:
*(struct s)p_obj needs to be *(struct s*)p_obj, as p_obj is not a structure object.
Because of operator precedence the expression (struct s*)p_obj->val is actually equal to (struct s*)(p_obj->val). Which means you try to dereference the void* pointer and cast the member val to struct s*.
You should do ((struct s*)p_obj)->val to cast the pointer p_obj.
And more typos: *void p_obj is very much wrong, it should be void* p_obj. Please take care to copy-paste your minimal, complete, and reproducible example, not retype is as that might add extra errors not in your real code, which distracts from the actual errors and problems.

Passing pointer to an array of pointers

I have a test function that takes an array as an argument. And I have an array of pointers. Can someone explain why I need to deference the pointer to an array of pointers when I pass it?
void test(States a[]){
cout << a[0].name << endl;
cout << a[1].name << endl;
}
Calling test():
States *pStates[MAX_STATES];
test(*pStates); //Or test(pStates[0])
//Can't do test(pStates);
You won't need to dereference if the arguments of test function expect so
void test(States *a[]);
But in your case, clearly the argument type is States [], so you need to pass a pointer.
You may want to consider rewriting test function as:
void test(States *a[]){
cout << a[0]->name << endl;
cout << a[1]->name << endl;
}
Use this instead:
void test(States* a[]){
cout << a[0]->name << endl;
cout << a[1]->name << endl;
}
And you won't need to dereference it...
The declaration of pStates declares an array of pointers. Not a pointer to an array.
However the function void test(States a[]); expects an array of objects (States objects).
You can't just cast one to the other.
#include <iostream>
typedef struct {
int name;
} States; //Surely this should be called State (not plural)
const size_t MAX_STATES=2;
void test(States a[]){
std::cout << a[0].name << std::endl;
std::cout << a[1].name << std::endl;
}
int main() {
States lFirst;
States lSecond;
lFirst.name=1;
lSecond.name=7;
//Here's what you had.
States*pStates[MAX_STATES];
//Now initialise it to point to some valid objects.
pStates[0]=&lFirst;
pStates[1]=&lSecond;
//Here's what you need to do.
States lTempStates[]={*pStates[0],*pStates[1]};
test(lTempStates);
return EXIT_SUCCESS;
}
Please see here https://stackoverflow.com/help/mcve

Passing char array by reference

I am passing a char array by reference but when I return from function and print the array, it displays nothing. What am I doing wrong?
#include <iostream>
using namespace std;
void func(char []);
int main()
{
char a[100];
func(a);
cout << a<<endl;
return 0;
}
void func(char *array)
{
array="Inserting data in array a";
cout << array<<endl;
}
Regards
What you can probably do is:
void func( char (& array)[10] ) {
}
According to the Spiral Rule, that is translated to: a reference (&) to an array of length 10 ([10]) characters (char).
You're not passing the array by reference (nor should you, it will do you no good here). You are passing a pointer to its first element. You then reassign that pointer to point to something else inside the function. This has no effect on the array. If you want to change the contents of the array, then you need to copy data to the place that the pointer points to. You can use strcpy or similar for that:
strcpy(array, "Inserting data in array a");
As a side comment, but a very important one. We don't need to deal with things like this in C++ anymore. That's how you do things in C. Here's how we do things in C++:
#include <string>
#include <iostream>
void func(std::string & str)
{
str = "Inserting data into the string";
std::cout << str << std::endl;
}
int main()
{
std::string a;
func(a);
std::cout << a << std::endl;
}
You can pass a pointer by reference. To do this you need to use the following syntax:
void func(char *&array)
{
// ....
}
Inside the function you use this parameter as a regular pointer. If the value that this pointer is pointing at is modified, these changes will be visible outside.
I used the answers above but I had to extend it, so I could print out the array's actual size like so:
template<size_t n> void foo(char (&array)[n])
{
// ...
std::cout << "array size: " << n << std::endl;
// ...
}
Try the following:
void function(char* MyArray)
{
MyArray = "Hello World";
std::cout << "Address of MyArray inside function: " << (void*)MyArray << std::endl;
}
int main()
{
char MyArray[10];
std::cout << "Address of MyArray outside function: " << (void*)MyArray << std::endl;
function(MyArray);
std::cout << "Address of MyArray outside function: " << (void*)MyArray << std::endl;
std::cin.get();
return 0;
}
With this you will see that the pointer to your array is only a copy inside the function. With assigning "Hello World" you only change the adress of the copy but not the adress of your array in the main function.
This example would actually work because this way you dont have copy of your pointer within the function:
void function(char** MyArray)
{
*MyArray = "Hello World";
std::cout << "Address of MyArray inside function: " << (void*)*MyArray << std::endl;
}
int main()
{
char* MyArray = 0;
std::cout << "Address of MyArray outside function: " << (void*)MyArray << std::endl;
function(&MyArray);
std::cout << "Address of MyArray outside function: " << (void*)MyArray << std::endl;
std::cin.get();
return 0;
}
But this is still bad style. When working with character arrays you should do something like this:
void function(char* MyArray)
{
strcpy(MyArray, "Hello World");
std::cout << "Address of MyArray inside function: " << (void*)MyArray << std::endl;
}
int main()
{
char* MyArray = 0;
MyArray = new char[15];
std::cout << "Address of MyArray outside function: " << (void*)MyArray << std::endl;
function(MyArray);
std::cout << "Address of MyArray outside function: " << (void*)MyArray << std::endl;
delete [] MyArray;
std::cin.get();
return 0;
}
But as others mentioned I would use std::string and pass it by reference also instead of using character arrays. Because character arrays are unsafe compared to std::string. Like this:
void function(std::string& MyString)
{
MyString = "Hello World";
}
int main()
{
std::string MyString;
function(MyString);
std::cin.get();
return 0;
}
You are passing a pointer to an array (func (char* array)) and then inside the function you are changing the pointer's value to point to the static string.
You either need to copy the new data into the array by means of strcpy() or pass the pointer to the array by reference:
void func(char*& array); // reference to pointer
Or:
strcpy(array, "data");
Better yet use std::vector<> or std::string instead.
Reference to native array is one of the very powerful C++ weapons. Plus templates. Here is one, perhaps non trivial but still simple example.
// set all element of a given native array reference
// to the same value
// return the reference to the same array
template<typename T, size_t N, typename array_type = T[N] >
inline
array_type& /* return reference to T[N] */
all_val
( T(&arf)[N], /* arg reference to T[N] */
T val )
{
// range for() works on native arrays
// begin(arf) / end(arf)
// work as expected
for (auto & elem : arf) {
elem = val ;
}
// array can not be returned by value
// but this is allowed in standard C++
// return type is native array reference
return arf;
}
When using the above, one should think and preserve returned type as native array reference.
using charray_type = char[0xF];
charray_type charray;
// decaying to pointer to T*
// you do not want this
auto pointer_to_char = all_val(charray, '*');
// you do want this
// preserving the ref to array
charray_type& charray_ref = all_val(charray, '*');
// normal native arr usage
charray_ref[0] = '*';
assert(charray[0] == charray_ref[0]);
I think this is rather simple and unique to standard C++.
I know this post is kind of old but I recently came across a style of passing char array as a reference and implemented it in your example ..
I have no Idea why when passing a char array as a reference you use [0] as the array index but this code works .
I spend allot of time looking around the web on how to do this so maybe it helps someone
#include <iostream>
using namespace std;
void func(char arr[3]);
int main()
{
char a[3];
a[0] ='a';
a[1] ='b';
a[2] ='c';
//passing the char array as a refrence
func(&a[0]);
cout<< "checking the values outside of the func"<<endl;
cout << a<<endl;
return 0;
}
void func(char arr[3])
{
cout<<"Inserting data in array a in the function " <<endl;
cout << &arr[0]<<endl;
}
The main idea behind passing an object as a reference is to not have a copy of the object as this could use up memory resources . So in the case of char array you might have very large array so it would be inefficient to send the whole char array objet as an argument . This is why we would pass by a reference instead
error first line iostream.h ...
and secondly you are not inserting any element into array...and you are passing a in your function, you have to pass address of your array into that function, but before that rewrite the code to have something in your array