Return a pointer to an array - c++

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].

Related

Vector of fn pointers doesn't reveal correct size()

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.

Adding objects to a pre allocated array of objects

#include <iostream>
class Object {
public:
int x;
Object() { }
Object(int x) {
this->x = x;
}
};
class SomeClass {
public:
Object array[10];
int n;
SomeClass() { n = 0; }
void insert(Object o) {
array[n++] = o;
}
};
int main() {
SomeClass s;
Object test = Object(4);
s.insert(test);
return 0;
}
I have this example where I pre-allocate an array of objects in SomeClass and then in some other method, main in this example, I create another object and add it to the array in SomeClass
One thing I think I should do is to switch from array[10] to an array of pointers so that I only create objects when I really need to.
But my question is what happens to the memory originally allocated for array[0] when I do "array[n++] = o" replacing it by the new object "o"? does it get de-allocated?
No, nothing happens. The object's assignment operator gets invoked, to replace the object.
For this simple class, the assignment operator is the default operator which, more or less, copies each of the object's members, one at a time.
(No need to get into move operators, etc..., just yet)

Pointer to pointer assignment isnt working

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);
// ^

Question on using this pointer

I tried copying a pointer to another by using a method inside the class and the this pointer as follows. I am giving the entire test code so that it is clear what is going on.
class test {
private:
int x;
public:
void setx(int x);
int getx(void);
void copy(test *temp);
};
void test::setx(int x) {
this->x = x;
}
int test::getx(void) {
return this->x;
}
void test::copy(test *temp) {
this = temp;
}
And I access this method from the main as follows:
int main() {
test a;
a.setx(4);
cout << a.getx()<<endl;
test *b = new test;
b->setx(4);
cout << b->getx()<<endl;
test *c;
c=b;
cout << c->getx()<<endl;
test *d;
d->copy(b);
cout << d->getx()<<endl;
}
However it gives the following error
In member function ‘void test::copy(test*)’:
error: lvalue required as left operand of assignment
All the other method involving the this pointer works fine except for the copying part. Am i doing some elementary mistake in using the this pointer?
You cannot overwrite this. The this pointer is a constant, so you're not allowed to change it. And what would that mean anyway? You can't change the object that you're in. You can change the values within that object, but not the object itself.
You need to copy other objects by value (by what is stored in the object), not by pointer.
Also, you shouldn't have a function called copy; that's what copy constructors and copy assignment operators are for.
You cannot modify the this pointer. You can however modify *this:
void test::copy(test *temp)
{
*this = *temp;
}
Also, you should rename the data member or the parameter, so you don't need this->:
class test
{
int m_x;
public:
void setx(int x)
{
m_x = x;
}
what is test::copy supposed to do?
Clearly you cant assign a different address to your current object. So it is invalid.
if this is supposed to initialize the current object with the values of some other object then it should look like this:
void test::copy(test *temp) {
this->x = temp->getX();
}

Is this C++ reassignment valid?

Sorry for the basic question, but I'm having trouble finding the right thing to google.
#include <iostream>
#include <string>
using namespace std;
class C {
public:
C(int n) {
x = new int(n);
}
~C( ) {
delete x;
}
int getX() {return *x;}
private:
int* x;
};
void main( ) {
C obj1 = C(3);
obj1 = C(4);
cout << obj1.getX() << endl;
}
It looks like it does the assignment correctly, then calls the destructor on obj1 leaving x with a garbage value rather than a value of 4. If this is valid, why does it do this?
If there is a class C that has a constructor that takes an int, is this code valid?
C obj1(3);
obj1=C(4);
Assuming C has an operator=(C) (which it will by default), the code is valid. What will happen is that in the first line obj1 is constructed with 3 as a the parameter to the constructor. Then on the second line, a temporary C object is constructed with 4 as a parameter and then operator= is invoked on obj1 with that temporary object as a parameter. After that the temporary object will be destructed.
If obj1 is in an invalid state after the assignment (but not before), there likely is a problem with C's operator=.
Update: If x really needs to be a pointer you have three options:
Let the user instead of the destructor decide when the value of x should be deleted by defining a destruction method that the user needs to call explicitly. This will cause memory leaks if the user forgets to do so.
Define operator= so that it will create a copy of the integer instead of a copy of the value. If in your real code you use a pointer to something that's much bigger than an int, this might be too expensive.
Use reference counting to keep track how many instances of C hold a pointer to the same object and delete the object when its count reaches 0.
If C contains a pointer to something, you pretty much always need to implement operator=. In your case it would have this signature
class C
{
public:
void operator=(const C& rhs)
{
// For each member in rhs, copy it to ourselves
}
// Your other member variables and methods go here...
};
I do not know enough deep, subtle C++ to explain the problem you are encountering. I do know, however, that it's a lot easier to make sure a class behaves the way you expect if you follow the Rule of Three, which the code you posted violates. Basically, it states that if you define any of the following you should define all three:
Destructor
Copy constructor
Assignment operator
Note as well that the assignment operator implementation needs to correctly handle the case where an object is assigned to itself (so-called "self assignment"). The following should work correctly (untested):
#include <iostream>
#include <string>
using namespace std;
class C {
public:
C(int n) {
x = new int(n);
}
C(const C &other): C(other.getX()) { }
~C( ) {
delete x;
}
void operator=(const C &other) {
// Just assign over x. You could reallocate if you first test
// that x != other.x (the pointers, not contents). The test is
// needed to make sure the code is self-assignment-safe.
*x = *(other.x);
}
int getX() {return *x;}
private:
int* x;
};
void main( ) {
C obj1 = C(3);
obj1 = C(4);
cout << obj1.getX() << endl;
}
Basically you are trying to re-implement a smart pointer.
This is not trivial to get correct for all situations.
Please look at the available smart pointers in the standard first.
A basic implementation (Which will fail under certain situations (copy one of the standard ones to get a better one)). But this should cover the basics:
class X
{
int* data;
public:
// Destructor obvious
~X()
{
delete data;
}
// Easy constructor.
X(int x)
:data(new int(x))
{}
// Copy constructor.
// Relatively obvious just do the same as the normal construcor.
// Get the value from the rhs (copy). Note A class is a friend of
// itself and thus you can access the private members of copy without
// having to use any accessor functions like getX()
X(X const& copy)
:data(new int(copy.x))
{}
// Assignment operator
// This is an example of the copy and swap idiom. This is probably overkill
// for this trivial example but provided here to show how it is used.
X& operator=(X const& copy)
{
X tmp(copy);
this->swap(tmp);
return this;
}
// Write a swap() operator.
// Mark it is as no-throw.
void swap(X& rhs) throws()
{
std::swap(data,rhs.data);
}
};
NEW:
What's happening is that your destructor has deallocated the memory allocated by the constructor of C(4). So the pointer you have copied over from C(4) is a dangling pointer i.e. it still points to the memory location of the deallocated memory
class C {
public:
C(int n) {
x = new int(n);
}
~C( ) {
//delete x; //Don't deallocate
}
void DeallocateX()
{
delete x;
}
int getX() {return *x;}
private:
int* x;
};
int main(int argc, char* argv[])
{
// Init with C(3)
C obj1 = C(3);
// Deallocate C(3)
obj1.DeallocateX();
// Allocate memory and store 4 with C(4) and pass the pointer over to obj1
obj1 = C(4);
// Use the value
cout << obj1.getX() << endl;
// Cleanup
obj1.DeallocateX();
return 0;
}
Be explicit about ownership of pointers! auto_ptr is great for this. Also, when creating a local don't do C obj1 = C(3) that creates two instances of C and initializes the first with the copy constructor of the second.
Heed The Guru.
class C {
public:
C(int n) : x(new int(n)) { }
int getX(){ return *x; }
C(const C& other) : x(new int(*other.x)){}
C& operator=(const C& other) { *x = *other.x; return *this; }
private:
std::auto_ptr<int> x;
};
int main() {
C obj1(3);
obj1 = C(4);
std::cout << obj1.getX() << std::endl;
}
When are you testing the value of obj1? Is it after you leave the scope?
In your example, obj1 is a stack object. That means as soon as you leave the function in which it defined, it gets cleaned up (the destructor is called). Try allocating the object on the heap:
C *obj1 = new C(3);
delete obj1;
obj1 = new C(4);