EDIT: I have fixed the accidental argument typo in func2() to be MyClass* not MyClass.
I have a class like this:
#include "MyClass.h"
class X{
public:
X();
MyClass* m;
func1();
func2(MyClass* m, int x);
private:
}
Source:
#include "X.h"
X::X{
m = null_ptr;
}
X::func1(){
//Pass the un-initialized data member m here...
func2(m, 6);
//When I get to this point m has not been assigned, even though it was passed as a pointer to func2()
}
X::func2(MyClass* old_obj, int x){
//Please forgive the memory management for a second....
MyClass* new_obj = new MyClass(x);
//This should initialise the data member m??????
old_obj = new_obj ;
}
However it doesn't work- am I making a fundamental miss-assumption here? I thought this would work....
To modify a pointer from function parameter, you need to modify original pointer not it's copy.
func2(MyClass*& m, int x);
// ^
Related
Below is a simplified example of the code I'm working on. There's a function that takes class A pointer as an argument. I want to pass a pointer that has been initialized as nullptr. Without initializing it to some garbage temporary value first, is it possible to pass the nullptr?
class A
{
// stuff
};
class B
{
public:
A* pA1;
A objA;
std::vector<A*> vecB;
B() : pA1 (nullptr) { vecB.push_back(&objA); }
};
void function(A* p);
A* pA2;
int main()
{
B objB;
pA2 = objB.vecB[0];
function(objB.pA1);
return 0;
}
void function(A* p)
{
p = pA2;
}
In a comment, you said:
The point of the function is to make this happen: objB.pA1 = pA2
I think what you need to do is pass a reference to the pointer, instead of passing a pointer by value. Use:
void function(A*& p) // The argument type needs to be "A* &", not "A*"
{
// Now, the change will be visible in the calling program.
p = pA2;
}
Yes. Any raw pointer type can be assigned and therefore initialised with the nullptr value. Example:
static A* pA2 = nullptr;
aschepter has given me the answer in a comment, thank you very much.
void function(A* p)
should be
void function(A*& p)
I have a vector of function pointers that is default initialized as a class member, so it always has 2 elements. However, when reading its size() I get gibberish. I have created a trivial, minimal replication of this problem below.
#include <iostream>
#include <vector>
using fnptr = float (*)(float);
float fn1(float x){ return x;};
float fn2(float x){ return x;};
std::vector<fnptr> fnptrs(){
std::vector<fnptr> ret;
ret.push_back(&fn1);
ret.push_back(&fn2);
return ret;
}
class Foo{
public:
int nFns()const{
return fns.size();
}
private:
std::vector<fnptr> fns = fnptrs(); // always initialized
};
class Baz {
public:
explicit Baz(Foo f):foo{&f}{}
const Foo* foo; // my problem does not appear if this is not a pointer
};
class Bar {
public:
explicit Bar(Foo f):foo{f}{
bazs.push_back(Baz(foo));
bazs.push_back(Baz(foo));
}
void viewSizes()const{
for (auto& i:bazs)
std::cout << " i.foo->nFns() = " << i.foo->nFns() << "\n";
}
const Foo foo;
std::vector<Baz> bazs;
};
int main(int argc, const char * argv[]) {
Foo f;
Bar b(f);
b.viewSizes();
return 0;
}
Output:
i.foo->nFns() = -677271344
i.foo->nFns() = -516
I do not prefer to store Foo in Baz as a pointer, but in my real program, I have a vector of Baz's that is swapped out frequently and a reference cannot be used for that (doesn't compile). If I make it a regular member (not a pointer or reference) then I have no problems, but with large numbers of these objects its better not to store the same copy in every object, so a pointer is what I need to use.
Here:
explicit Baz(Foo f):foo{&f}{}
f is a local variable of the constructor and evaporates once the constructor exits. You probably want to pass a reference, or an actual raw pointer instead.
I have a class that has a setter method which takes a unique_ptr as an argument. That unique_ptr is saved as a class member.
class TestClass {
std::unique_ptr<Tester> sp;
void setTester_Way1(std::unique_ptr<Tester> te) {
auto deleter=std::move(sp);
sp=std::move(te);
}
void setTester_Way2(std::unique_ptr<Tester> te) {
sp=std::move(te);
}
};
Which way is the correct way to set the smart pointer? Does Way2 leak the original pointer of sp?
Way2 is fine, when you assign to a unique_ptr any existing owned pointer will be safely deleted.
As Chris Drew said Way2 is fine. One thing though is that unique_ptr is not copyable/assignable so the only ways to pass a unique_ptr is by reference, r-value reference or by value with move(). Trying to do:
int main()
{
TestClass t;
auto p = std::make_unique<int>(10);
t.setTester_Way2(p);
}
Will fail to compile. Although you can move() p into the function(example).
If you change setTester_Way2() to void setTester_Way2(std::unique_ptr<int>& te) then it will compile. If you change the function to take an rvalue reference and std::move() the pointer into the funcnction:
class TestClass {
std::unique_ptr<int> sp;
public:
void setTester_Way1(std::unique_ptr<int> te) {
auto deleter=std::move(sp);
sp=std::move(te);
}
void setTester_Way2(std::unique_ptr<int>&& te) {
sp=std::move(te);
}
};
int main()
{
TestClass t;
auto p = std::make_unique<int>(10);
t.setTester_Way2(std::move(p));
}
Then it will also compile.
I have a getter method that returns an array declared private.
In .h:
private:
CStringArray a;
In . cpp:
CStringArray &Define::GetDefined()
{
return a;
}
In another .cpp:
int size = (define.GetDefined()).GetCount();
This does return the right value of int. But is this the correct example of assigning by reference?
Yes, although the extra braces in the final .cpp file are unnecessary and are not helpful to the reader so you should probably not bother
eg.
int size = define.GetDefined().GetCount();
You should probably also mention that the user should be sure that the object being returned by referance is not allocated on some part of the stack that is about to become invalid.
for example:
A& method() {
return A();
}
or any part of memory that is about to become invalid for that matter:
class A{
B member;
B& get_b_ref() {
return member;
}
}
int main() {
A* a_ptr = new A();
B& b_ref = a_ptr->get_b_ref();
delete a_ptr;
b_ref.any_method(); // yikes
}
Yes, it's absolutely correct to return reference from the getter.
You might even want to return const Array &, if this object should not be modified from outside
Suppose you have a class with a private pointer to an array. How can you use a getter to access (or effectively copy the data) so you can access it in a different variable.
class MyClass
{
private:
double *x;
public:
myClass();
virtual ~MyClass();
double* getX() const;
void setX(double* input);
};
MyClass::MyClass()
{
double foo[2];
double * xInput;
foo[0] = 1;
foo[1] = 2;
xInput = foo;
setX(xInput);
}
void MyClass::setX(double * input)
{
x = input;
}
double * MyClass::getX() const;
{
return x;
}
int main()
{
MyClass spam(); // Construct object
double * bar = spam.getX(); // This doesn't work
}
In this case, bar[0] and bar[1] are equal to jibberish: -9.2559631349317831e+061.
MyClass spam(); // Construct object
That does not construct an object, that declares a function called spam that takes no arguments and returns a MyClass. This default constructs an object:
MyClass spam; // Construct object
For more information google the most vexing parse.
Update: As #Mark Ransom pointed out, there is another problem with your code. In your constructor you create an array, and then set x to point to such array. However the array lifetime ends once the constructor finishes execution, so further access to x would crash (if you are lucky enough).
Just a guess, the program is crashing or showing the wrong output. This is because the constructor is setting a pointer to a local array, which leaves scope and gets destroyed at the end of the constructor.
That should probably be *bar instead of bar[0].