When your question is answered use !solved to mark the question as resolved.
Remember to ask specific questions, provide necessary details, and reduce your question to its simplest form. For tips on how to ask a good question run !howto ask.
80 messages · Page 1 of 1 (latest)
When your question is answered use !solved to mark the question as resolved.
Remember to ask specific questions, provide necessary details, and reduce your question to its simplest form. For tips on how to ask a good question run !howto ask.
What's the problem?
If you want to inherit from dot, you can do this only 1 time afaik
No no is there a better method than this one u showed me
Like
hmm
This one here creates two additional dots which would lead to using destructor twice more?
So can we avoid it somehow and use it only here would be 3 times?
A Circle usually has only 1 mid-point (dot), right?
class Base
{
public:
Base(int x) : a{ x } {}
private:
int a{};
};
class Derived : public Base
{
public:
Derived(int a, int b)
: Base{ a }
, x { b } {}
private:
Int x{};
};
yess, but im not talking about how many dots does circle have, instead how can i avoid creating two additional dots just to init A and B
you mean initializer lists?
Ok, I understand now
You can probably use std::move() to transfer ownership of the dots
If you have 2 dots then you will construct and destruct two no matter what
im not eaxctly sure what this list is but let me explain it as much as i can!
If i were to have:
** dot( int, int ) *
I wouldnt make
int x = 5;
int y = 3:
just so i can say
dot A( x, y );
instead you would use A's constructor and say
dot A( 5 , 3 )?
So same here, want to use A's constructor directly from main.
this one is the closest one to what im trying to achieve
What I can understand is you are confused in OOP
it just feels a bit strnage saying
Circle c(
dot(100.0,150.0),
dot(200.0,300.0)
);
yes
Ok
Let me be clear
You want to initialise the dot in A's constructor without using dot's constructor.
Am I right ?
no, i want to use its constructor!
Of course that works ```c++
class dot {
float x,y;
public:
dot(float x = 0.0, float y = 0.0) : x(x), y(y) {};
};
class Circle {
protected:
float p;
dot A, B;
public:
Circle( dot a, dot b, float r = 0.0 ) : A( a ), B( b ), p(r) {};
};
int main(int argc, char *argv[]) {
dot a(100.0,150.0);
dot b(200.0,300.0);
Circle c(a, b);
}
He is asking about implicit calling
You can use it like this also --
Circle a({100, 200}, {100, 200})
what im trying to achieve somehow if its possible i dont know it is:
class dot {
float x,y;
public:
dot(float x = 0.0, float y = 0.0) : x(x), y(y) {};
};
class Circle {
protected:
float p;
dot A, B;
public:
Circle( dot a, dot b, float r = 0.0 ) : A( a ), B( b ), p(r) {};
};
int main(int argc, char *argv[]) {
// dot a(100.0,150.0);
// dot b(200.0,300.0);
Circle c(a( 100.0, 50.0 ), b( 200.0, 300.0 ) );
}
You can use it like this also --
Circle a({100, 200}, {100, 200})
Circle a(dot(100, 200), dot(100,200))
Circle a(dot(100, 200), dot(100,200))
this one is hard for me to understand
Unfortunately C++ has no named parameters
how come its okay to do dot(smth.) instead of a(smth.)
Circle( dot a, dot b, float r = 0.0 )
U call it by the class and not the variable name
which feels weird to me
but its fine ill get used to it eventually
anyway
thanks
I already showed you a different way which uses implicit call to dot's constructor
You can use that way if you want.
Circle( dot a, dot b, float r = 0.0 ) a,b,r are parameters - dot and float the types
!solved
Thank you and let us know if you have any more questions!
@mental wadi Do you know why the destructor is called 4 times? ```c++
#include <iostream>
#include <utility>
class dot {
float x,y;
public:
dot(float x, float y) : x(x), y(y) {};
virtual ~dot() {
std::cout << "dot.destructor" << std::endl;
}
};
class Circle {
protected:
float p;
dot A, B;
public:
Circle( dot&& a, dot&& b, float r = 0.0 ) : A( std::move(a) ), B( std::move(b) ), p(r) {};
};
int main(int argc, char *argv[]) {
Circle c(
dot(100.0,150.0),
dot(200.0,300.0)
);
}
I think that is what @void swallow wanted to avoid
To be precise destructor will be called 3 times. Twice for destroying the 2 member variable of type dot in Circle, then once for the Circle itself
I get this output: ```
dot.destructor
dot.destructor
dot.destructor
dot.destructor
So it's 4 times instead of the desired 2
;compile
dot.destructor
dot.destructor
dot.destructor
dot.destructor
I'm new to modern C++ for 3 days only, sorry. Did some C++98 15 years ago.
C++ works on the principle of "You pay for what you want". If you wanted something then you pay for it and you can't escape from it...
My understanding is that std::move() transfers the ownership, but somehow 4 dot() get constructed
Can we avoid that somehow?
First you need to understand why 4 dot's are getting constructed. Then you will have answer to your question.
When you are calling Circle(dot( ... ), dot( ... )) You are creating two temporary dots which are getting copied into the two dots inside Circle. And then those two temporary are destroyed after getting copied. Destructor count = 2.
Then the actual member variable inside Circle in which you copied are getting destroyed when Circle is getting destroyed. Destructor count = 2.
Which is why dot's destructor is getting called twice.
I tried to avoid that using std::move()
Looks like std::move() does not what I think
You cannot avoid it.
Because you need something to copy. Whether it be permanent or temporary object it needs to get constructed. And if it temporary then it will gets destroyed when required automatically...
The summary is whether it be temporary or permanent if you construct it, it will be destroyed at some point
Got it now, std::move() works fine with pointer transfer
#include <iostream>
#include <utility>
class dot {
float x,y;
public:
dot(float x, float y) : x(x), y(y) {};
virtual ~dot() {
std::cout << "dot.destructor" << std::endl;
}
};
class Circle {
protected:
float p;
dot *A, *B;
public:
Circle( dot* a, dot* b, float r = 0.0 ) : A( std::move(a) ), B( std::move(b) ) , p(r) {
};
virtual ~Circle() {
delete A;
delete B;
std::cout << "Circle.destructor" << std::endl;
}
};
int main(int argc, char *argv[]) {
Circle c(
new dot(100.0,150.0),
new dot(200.0,300.0)
);
}
;compile
dot.destructor
dot.destructor
Circle.destructor
Okay, thanks for your time @mental wadi!
Now you have a memory leak with new
I'm moving ownership using std::move() 🤷♂️
Because if you allocate something with new then you are responsible to free that memory using delete. C++ doesn't do that for you
What is std::move ?
Do you know what it does ?
"std::move is used to indicate that an object t may be "moved from", i.e. allowing the efficient transfer of resources from t to another object."
I'm moving ownership of the 2 new dot() into Circle and delete them in the Circle destructor
std::move casts an lvalue into rvalue. Which means std::move moves the resources inside an object. In your case you allocated memory using new, then moves the resources from that memory, but you did not deallocate that memory and there you got memory leak
Looks good to me, as expected: ```c++
#include <iostream>
#include <utility>
class dot {
float x,y;
public:
dot(float x, float y) : x(x), y(y) {};
virtual ~dot() {
std::cout << "dot.destructor" << std::endl;
}
};
class Circle {
protected:
float p;
dot A, B;
public:
Circle( dot a, dot b, float r = 0.0 ) : A( std::move(a) ), B( std::move(b) ) , p(r) {
};
virtual ~Circle() {
delete A;
delete B;
std::cout << "Circle.destructor" << std::endl;
}
};
int main(int argc, char *argv[]) {
auto a = new dot(100.0,150.0);
auto b = new dot(200.0,300.0);
Circle c( a, b );
//delete a;
//delete b;
}
Here you used new outside the function and hence you have controll over it and can delete it. But when you use new in a function parameter, then you have no control over it afterwards because you which you get memory leak
Thanks! 👍
If you are taking rvalue reference in function. Then you can call the constructor like this --
Circle a(std::move(dot{100, 200}), std::move(dot{100, 200}))
That will still call the destructor
If you are wondering why destructor is not getting called with pointers. It's because those dynamically allocated objects are not getting destroyed at the end of the function.