If i have the following part of the code in C++:
class X {
...
};
class Y {
public:
Y(X*) {...};
...
};
void main ()
{
X* px = new X;
new Y(px);
... // ***
}
How to delete object of class Y which was created in main? (*)
It is only allowed to add new lines of code instead of ..., not to change existing ones.
Disclaimer Never write code like this; avoid dynamic objects when you can, and if you really need them, always use RAII to manage them in a straightforward, exception-safe way.
Replace the first ... with:
#define void int
since void main () is invalid, and my compiler rejects it. This might not be necessary if your compiler is sufficiently dysfunctional.
Replace the second with:
WTF() = this;
to stash a pointer to the object that will need deleting in a static variable, defined later. Note that this only allows us to control one such object at a time; but, given the insane requirements, I can't think of a better way to make it available. If the constructor argument were available, then we could stash it in a non-static member of X instead; but the argument is unnamed, so we can't do anything with it.
Repace the third with:
static Y *& WTF() {static Y * y; return y;}
giving us a static variable to stash the pointer in. It can't be a global or static class member, since they must be defined outside the class definition.
Now we can replace the fourth with:
delete Y::WTF();
delete px;
Without the weird requirements, you could replace the whole mess with:
int main() {
X x;
Y y(&x);
}
The lesson from all this is: memory management in C++ is quite straightforward if you do it the right way, and insanely convoluted if you do it the wrong way.
I completely agree with Mike's answer, but I'd like to give an example of a working code, as opposed to Luchian's
class X {
public: void*data;
};
class Y {
public:
Y(X*px)
{ px->data = this; };
};
int main ()
{
X* px = new X;
new Y(px);
delete static_cast<Y*>(px->data);
return 0;
}
Related
I want to initialize member object variables in the default constructor of the class.
Let's consider the following,
class ABC {
ABC(int A, int B) {
a = A;
b = B;
}
int a;
int b;
};
class Foo {
Foo();
ABC m_obj1;
};
From the above example, I would like to initialize "obj1" in "Foo::Foo()".
One of the restrictions I have is that I cannot do so in the initializer list, as I need to do some computation before I could initialize the member. So the option available (ASFAIK) is to do so in the body of the default constructor only.
Any inputs, how could I do this?
Edit: Restricting to C++11
Would this be a correct way,
Foo:Foo() {
int x = 10;
int y = 100;
m_Obj1(x, y); //Is this correct? <--------
}
Depending on your exact problem and requirements, multiple solutions might be available:
Option 1: Use a function to do the computations and call Foo constructor
Foo makeFoo()
{
// Computations here that initialize A and B for obj1 constructor
return Foo(A, B)
}
Option 2: Call a function that does the computations and initialize obj1 in Foo member initializer list
ABC initABC() {
// Some computations
return ABC(A, B)
}
Foo() : obj1(initABC()) {}
Option 3: Dynamically allocate obj1, for instance with a std::unique_ptr
Option 4: Use std::optional or an emulated c++11 version as shown by other answers
You simply call the base constructor inside the initializer list of the derived constructor. The initializer list starts with ":" after the parameters of the constructor. See example code!
There is no problem to call functions inside the initializer list itself.
int CallFunc1(int x) { return x*2; }
int CallFunc2(int y) { return y*4; }
class ABC {
public:
ABC(int A, int B):a{CallFunc1(A)},b{CallFunc2(B)} {
std::cout << "Constructor with " << a << " " << b << " called" << std::endl;
}
private:
int a;
int b;
};
class Foo {
public:
Foo(): obj1(1,2){}
Foo( int a, int b): obj1(a, b){}
private:
ABC obj1;
};
int main()
{
Foo foo;
Foo fooo( 9,10);
}
edit:
The best method I can think of for your case is a copy constructor, being more specific on what you need to store helps a lot since if it is just two ints inside a class dynamic allocation is not worth it, the size of the object being constructed makes a difference to what method is best, copy constructors can be slower with much larger data types as the object has to be created twice: once when it is automatically constructed in the parent objects constructor and again when a temporary object is created and all the values have to be copied, which can be slower then dynamically allocating if the size is larger.
As far as I'm aware all objects in a class are automatically initialized/allocated in the constructor so sadly dynamic memory use may be your best bet here.
If you are fine with having the object initialized but empty so you know it is not 'ready' yet you can later fill it with useful data when you would have wanted to initialize it. This can be done with default constructors that set the things inside the object to null values or something similar so you know the object hasn't been properly initialized yet. Then before using the object you can check whether it has been initialized by checking for the null values or by having put a bool in the object that tells you whether it is initialized. Dynamically allocated would still be better in my opinion and makes the code look cleaner overall as all you need to store is a null pointer until the object is needed and then allocated and set to the pointer. It is also very easy to check if the pointer is equal to nullptr to know the state of your object.
Dynamically allocating memory may be a hassle since you have to make sure to get rid of memory leaks and it is slightly slower than using the stack, but it is a necessary skill for c++ since the stack is not enough when making programs that use more than the few available megabytes of data on the stack so if you are doing this simply to avoid the hassle I recommend learning it properly. It would be nice if you could be more specific about what kind of object you want to do this with or if you just want an answer that works for most cases.
eg:
*ABC obj1 = nullptr;
...object is needed
obj1 = new(ABC(constructor stuff));
...obj1 isn't needed
delete obj1;
or c++ automatically deletes it when the program closes.
Title may be misleading, not sure how to explain this but I'll provide an example.
So I have this structures:
struct mom {
public:
static constexpr auto create(int i) {
return a(i);
}
struct a {
int* m_a;
constexpr a(int i) : m_a(&i) {
change();
}
constexpr void change(void) {
*m_a += 100;
}
struct b {
public:
static int get(a* import) {
int* arr = new int[10];
arr[1] = *import->m_a;
return arr[1];
}
};
};
};
And I call it like this:
printf("%d", mom::a::b::get(&(mom::create(10))));
It is supposed to add 100 the 10 (or any other value you give it) at compile time, then at runtime to store it into a dynamic array and return it to you.
This code is almost exact to my project, but it has a problem: instead of adding 100 to the value, it returns a random big number (-95321314). I tried debugging it and it is all fine until I call the get() function in which I have no idea what is happening that causes this
any ideas?
The problem is m_a is a pointer to a temporary, as soon the stack unwinds further usage of that temporary is undefined.
Specifically, the call to mom::create(10) returns a struct a, whose member m_a is no longer pointing to a valid region of memory. Subsequent usage of that member will be undefined (e.g. the copy into b's array in get())
A simple "fix" would be to change m_a(&i) -> m_a(new int(i)), although note that this introduces a memory leak and changes the memory layout entirely. Since it's not clear to me what your design goals are, it's a reasonable alternative to get things "working".
I can't remember what it is called, but I know i can do it in Java.
Suppose I have the following:
class Foo
{
public:
Foo() {};
void bar() {};
};
I want to do this:
int main() {
(new Foo).bar();
}
But it doesn't seem to work. Is there a similar way to do this without having to do:
int main() {
Foo foobar;
foobar.bar();
}
new dynamically-allocates memory and returns a pointer. Class members are obtained using the indirection operator ->. I don't think this is what you're looking for as you run the risk of causing a memory leak. Simply calling the constructor of Foo allows us to do what we want:
Foo().bar();
By calling the constructor of Foo, we create a temporary object off of which we can obtain its data members. This is preferred over pointers as we don't have to deal with memory leaks and deletion of the pointer.
You can say (new Foo)->bar();. That works but is absolutely idiotic. The correct thing is this:
int main()
{
Foo x;
x.bar();
}
Or, if you don't want the local variable: Foo().bar();. But now that's questionable, since if you don't need Foo to be stateful, then you probably don't need a class at all. Just make bar a free function (something that doesn't exist in Java):
void bar();
int main()
{
bar();
}
Yes, Foo().bar();. No need to use new like in Java.
I'm relatively new to C++ and I'm wondering if structs are copied in the following case:
struct foo {
int i;
std::vector<int> bar;
}
class Foobar {
foo m_foo;
void store(foo& f) {
this->m_foo = f;
}
}
void main() {
Foobar foobar;
{
foo f;
f.i = 1;
f.bar.insert(2);
foobar.store(f);
}
// will a copy of f still exist in foobar.m_foo, or am I storing a NULL-Pointer at this point?
}
The reason why I am asking this is that I am originally a .NET developer and in .NET structures will be copied if you pass them to a function (and classes are not).
I'm pretty sure it would be copied if store was not declared to take f by reference, but I cannot change this code.
Edit: Updated the code, because I didn't know that the vector.insert would affect my question. In my case I store the struct as a member in a class, not a vector.
So my question really was: will f be copied at this->m_foo = f;?
Short answer: Yes.
Long answer: You'd have to get a pointer to a stack allocated struct and then let that struct go out of scope in order to end up with a dangling reference in your vector... but even then, you wouldn't have stored a NULL. C and C++ pointers are simple things, and will continue to point at a memory location long after that memory location has become invalid, if your code doesn't overwrite them.
It might also be worth noting that std::vector has a decent set of copy and move functions associated with it that will be called implicitly in this case, so the bar vector inside the struct will also be copied along with the simple integer i. Standard library classes tend to be quite well written, but code by other folk has no such guarantee!
Now, as regards your edit:
class Foobar {
foo m_foo;
void store(foo& f) {
this->m_foo = f;
}
}
You will still not have any problems with the foo instance stored in m_foo. This is because this->m_foo = f invokes a copying operation, as m_foo is not a variable of a reference or pointer type. If you had this instead: foo& m_foo then you would run into difficulties because instead of copying a foo instance you are instead copying a reference to a foo instance, and when that instance goes out of scope, the reference is no longer valid.
Yes, the struct will be copied, in the following function:
foos.insert(f);
As a copy is made, you won't be storing a null pointer / null reference.
However, like you've said, it won't be copied when you call store(f); as the function accepts the argument as a reference.
Your edit will still make a copy of Foo. You are assigning one instance of a variable to another instance of a variable. What you aren't doing is assigning one pointer (reference in C#) to another. You could probably do with doing some reading around C++ object instances, pointers, and references.
A copy of f is made during foos.insert(f)
void store(foo& f) {
foos.insert(f);
}
void main() {
{
foo f;
f.i = 1;
f.bar.insert(2);
store(f);
}
// at this place, local variable `f` runs out of scope, it's destroyed and cleaned up
// foos is holding the copy of `f`
}
I know this may sound strange, but yes, it's 2009 and I need to write small application using BCB5 :)
The problem is that DynamicArray throws OutOfBound exception when trying to expand it from within worker thread.
I have global variable, let's say
DynamicArray<double> X;
In main thread I check the length of array and I get 0, which is OK (length wasn't set)
Application->MessageBox(itoa(X.Length,str , 10), "", MB_OK);
Below is my worker thread class
class ArrayModifierThread : public TThread
{
private:
DynamicArray<double> __thread X;
protected:
void __fastcall Execute();
public:
__fastcall ArrayModifierThread(bool CreateSuspended);
void setX(DynamicArray<double> &a);
};
So far so good. Next I create new thread:
ArrayModifierThread *t = new ArrayModifierThread(true);
t->setX(X); // Pass reference to my global DynamicArray
t->Resume();
Here the Execute() method gets executed:
void __fastcall ArrayModifierThread::Execute()
{
X.Length = 10;
X[5] = 45.5;
}
What I'd expect is that global array is expanded and 6th element gets value of 45.5.
But closer investigation from within main thread gives Length = 0 and ArrayOfBounds Exception:
Application->MessageBox(itoa(__X.Length,str , 10), "", MB_OK);
Application->MessageBox(itoa(__X[5],str , 10), "", MB_OK);
Could anybody tell me what I've missed?
In your Execute method you're modifying the thread's X field, not the global X variable. Although the setX method receives its argument by reference, the member variable is not a reference. It stores a copy of the DynamicArray value, and changing the Length property ensures that it refers to a unique array.
The setX function receives a reference to the global variable, as you correctly observe in your "answer," but it doesn't keep a reference to it. It instead makes a copy of it when it assigns the object's X field.
Perhaps you intended to declare X as a reference as well:
private:
DynamicArray<double>& X;
That could work. Your setX function wouldn't work anymore since you're not allowed to "re-seat" a reference after it's been initialized. Instead, you'd need to initialize it in the thread's constructor:
ArrayModifierThread(DynamicArray<double>& a): X(a) { ... }
You could also store a pointer to the array instead of a reference:
private:
DynamicArray<double>* X;
public:
void setX(DynamicArray<double>& a) {
X = &a;
}
protected:
void Execute() {
X->Length = 10;
(*X)[5] = 45.5;
}
Something else you need to be aware of is that your code is not thread-safe. (Neither is mine here.) You have multiple threads modifying the same shared resource (the array) without any protection, such as a critical section. That's beyond the scope of this question, though. Search Stack Overflow and the rest of the Web first, and then come back to ask a new question if you need help with that issue.
It will not work as the member X is not a reference. When you call set() you are making a local copy of the object, then Execute() is modifying the local version.
class ArrayModifierThread : public TThread
{
private:
DynamicArray<double> __thread X;
void __fastcall ArrayModifierThread::Execute()
{
X.Length = 10;
X[5] = 45.5;
}
There are three alternative solutions:
Make the your local member variable X a reference.
Since the reference must be initialized on construction you can not use set() to modify it, so pass the reference to the constructor of your object and save it there.
Make the your local member variable X a pointer.
When using set() take the address of the passed in parameter (note it is a reference so you will get the address of the object it is referencing). This also means that the execute needs to be modified to take into account that X is a pointer.
Do not use a local member variable. Just modify the global directly.
Well, it's not quite clear to me.
I thought because of void setX(DynamicArray &a) the worker thread gets a reference to a global variable.
Could you post sample code how should it be done?
This is how my void setX(DynamicArray &a) looks like:
void ArrayModifierThread::setX(DynamicArray<double> &a)
{
X = a;
}