#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)
Related
I am trying to initialize a dynamically created array of objects of a class. This class has both a default constructor, a two-parameter constructor and a destructor in addition to its members.
#include <someLibrary.h> // Some C library
class A {
// some member variables
public:
A() {}
A(unsigned p1, int p2)
{
initLibrary();
}
~A()
{
terminateLibrary();
}
// other member functions
}
int main()
{
unsigned nObj = 5;
A *obj = new A[nObj];
for (int i = 0; i<nObj; i++) {
obj[i] = A(i, -42); // destructor called here, when it shouldn't
}
// Do some things with member functions of objects
return 0;
// need destructor to be call only here
}
In the two-parameter constructor, I initialize a library. This constructor is called inside the for loop of the main() function as you can see. In the destructor, I am terminating said library. I need to perform some actions pertaining to the library in the member functions of the objects. So, I can't terminate the library before the end of the main() function. However, in my implementation (above), the destructor is called right after I initialize the object in the for loop.
I understand why in that this is simply an assignment rather than initialization. So, the destructor is called to destroy the temporary object which is created during assignment.
But, how can I achieve initialization of each object of a dynamically created array of objects using the two-paramter constructor without a destructor call?
A *obj = new A[nObj];
for (int i = 0; i<nObj; i++) {
obj[i] = A(i, -42); // destructor called here, when it shouldn't
}
You are creating an array with nObj number of default-constructed objects, and then each loop iteration is creating a new temporary object and copy-assigning it to an array element. The destructor is called when each temporary object goes out of scope.
return 0;
// need destructor to be call only here
Even if you were to rewrite the code to avoid the temporary objects, the destructors still won't be called, because you are not delete[]'ing the array, and thus not destroying the objects in it. You are leaking the array. You should use std::vector to avoid that.
In the two-parameter constructor, I initialize a library. This constructor is called inside the for loop of the main() function as you can see. In the destructor, I am terminating said library.
Why are you re-initializing the library on every object creation, and terminating the library on every object destruction? That makes no sense.
If you really need to handle the library like that, you should consider putting a static reference count in the class so only the first object created actually initializes the library, and the last object destroyed actually terminates the library. Then it won't matter how many objects you create in between, eg:
class A {
// some member variables
static size_t refCnt = 0;
public:
A()
{
if (++refCnt == 1)
initLibrary();
...
}
A(unsigned p1, int p2)
{
if (++refCnt == 1)
initLibrary();
...
}
A(const A&)
{
++refCnt;
...
}
A(A&&)
{
++refCnt;
...
}
~A()
{
...
if (--refCnt == 0)
terminateLibrary();
}
// other member functions
};
Alternatively:
class A {
// some member variables
struct libInit
{
libInit(){ initLibrary(); }
~libInit(){ terminateLibrary(); }
};
static std::shared_ptr<libInit> s_lib = std::make_shared<libInit>();
std::shared_ptr<libInit> m_lib;
public:
A()
{
m_lib = s_lib;
...
}
A(unsigned p1, int p2)
{
m_lib = s_lib;
...
}
A(const A& a)
{
m_lib = a.m_lib;
...
}
A(A&& a)
{
m_lib = std::move(a.m_lib);
...
}
~A()
{
...
}
// other member functions
};
Otherwise, consider moving the library initialization/cleanup out of your class altogether. It should be handled by main() itself, either directly, or in another class that main() creates only 1 object of.
I can't terminate the library before the end of the main() function.
All the more reason why the library initialization/cleanup doesn't really belong in your array to begin with. It should be handled in main() before creating the array, and after destroying the array, eg:
int main()
{
initLibrary();
unsigned nObj = 5;
std::vector<A> obj(nObj);
for (A &elem : obj) {
elem = A(i, -42);
}
// Do some things with member functions of objects
obj.clear();
terminateLibrary();
return 0;
}
Alternatively:
#include <vector>
struct libInit
{
libInit(){ initLibrary(); }
~libInit(){ terminateLibrary(); }
};
int main()
{
libInit lib;
unsigned nObj = 5;
std::vector<A> obj(nObj);
for (A &elem : obj) {
elem = A(i, -42);
}
// Do some things with member functions of objects
return 0;
}
But, how can I achieve initialization of each object of a dynamically created array of objects using the two-paramter constructor without a destructor call?
The simplest way is to just add a method to your class, which you can call on the array's default-created objects, eg:
int main()
{
unsigned nObj = 5;
std::vector<A> obj(nObj);
for (A &elem : obj) {
elem.init(i, -42);
}
// Do some things with member functions of objects
return 0;
}
Otherwise, if you want to construct each array element using a non-default constructor, you would have to change the array to be just raw bytes of sufficient size, and then use placement-new to construct the individual objects within those bytes at the appropriate offsets, eg:
#include <type_traits>
#include <memory>
#include <new>
class A {
...
};
int main()
{
unsigned nObj = 5;
std::vector< std::aligned_storage<sizeof(A), alignof(A)>::type > obj(nObj);
for (auto &elem : obj) {
new (&elem) A(i, -42);
}
// Do some things with member functions of objects
for (auto &elem : obj) {
A *a = std::launder(reinterpret_cast<A*>(&elem));
a->doThings();
}
// cleanup
for (auto &elem : obj) {
A *a = std::launder(reinterpret_cast<A*>(&elem));
std::destroy_at(a);
}
return 0;
}
I want to know is it okay if i will use following method? There is no syntax errors and any warnings but i want to know is there any memory problems?
#include <iostream>
using namespace std;
class test {
int* x;
public:
test(int *n) { this->x = new int(*n); }
inline int get() { return *x; }
~test() { delete x; }
};
int main(void) {
while(1){
test a(new int(3));
cout << a.get() << endl;
}
return 0;
}
You have 2 issues in your code:
your class violates rule of three/five/zero
you are leaking memory when create a
In this code:
test a(new int(3));
you dynamically allocate int with value 3 and pass to a ctor which uses value and creates it's own dynamically allocated int. After that this memory is leaked. If you want to pass dynamically allocated data to a class use a smart pointer:
class test {
std::unique_ptr<int> x;
public:
test(std::unique_ptr<int> n) : x( std::move( n ) ) { }
int get() const { return *x; }
};
int main()
{
x a( std::make_unique<int>( 3 ) ); // since c++14
x a( std::unique_ptr<int>( new int(3) ) ); // before c++14
...
}
and you do not need to implement dtor explicitly, you do not violate the rule and it is safe to pass dynamically allocated data to ctor.
Note: I assumed you used int as example and you would understand that dynamically allocate one int is useless, you should just store it by value.
You are violating the rule of 3 (5 since c++11). It means that since you defined the destructor you should define the copy/move constructor/operation.
With your implementation, the copy/move constructor/operation are wrong. When you copy your object, it will do a shallow copy of your pointer and will delete it therefore you will have a double delete. When you move it, you will delete a pointer you didn't allocated.
Bonus point: your inline is useless
Consider the following simple program. It just defines two variables A and B from MyStruct and then initializes A.
How can I copy A to B with new pointers for B?
If I use assignment operator, firstMember of B will be assigned with firstMember of A and whenever I change the value of B.firstMember[i], the value of A.firstMember[i] will change. I already know that it can be done with a function, but is there any simpler way? Assuming that MyStruct can have lots pointers, writing a function doesn't seem to be good.
typedef struct MyStruct
{
int * firstMember;
int secondMember;
} MyStruct;
int main()
{
MyStruct A;
MyStruct B;
Initialize(A); // initializes A such that A.firstMember[0] != 5
B = A;
B.firstMember[0] = 5;
cout<<A.firstMember[0]; // prints 5
return 0;
}
This falls into the "Rule of 3". Once you start managing raw pointers inside a class, you probably want to define a custom contructor, destructor, and assignment operator for this very reason.
First of all, I don't understand why among two members, one is a pointer, and other is not. I am presuming that the first member which is a pointer points to a single integer. Here's an improved code snippet for the structure:
struct MyStruct
{
int * firstMember;
int secondMember;
MyStruct& operator = (const MyStruct& src) {
*firstMember = *src.firstMember;
return *this;
}
MyStruct(int a = 0) {
firstMember = new int(a);
secondMember = a;
}
MyStruct(const MyStruct& src) {
// deep copy
firstMember = new int(*src.firstMember);
secondMember = src.secondMember;
}
~MyStruct() {
if (firstMember)
delete firstMember;
}
};
Note, struct is a class with all members declared as public by default. Rather than having Initialize in C-way, better to use C++ proper construct like constructor, and you need to have copy constructor and assignment operator too.
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].
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);