This question already has answers here:
Two calls to destructor
(3 answers)
Closed 4 years ago.
am new to c++ and and trying to learn the cost of copying values or passing references, in my example I found though a segment of code that is for me hard to understand:
consider this example:
struct Foo {
Foo(int x) :
internVal { x } {
std::cout << "Con: " << std::endl;
}
~Foo() {
std::cout << "Des: " << std::endl;
}
int getVal() const {
return internVal;
}
private:
int internVal { 0 };
};
now when I do:
int main(int argc, char **argv) {
{
Foo a { 111 };
Foo b { 6555 };
Foo c { -444 };
std::cout << " Foos created..." << std::endl;
std::vector<Foo> vector_Test { };
vector_Test.push_back(a);
vector_Test.push_back(b);
vector_Test.push_back(c);
std::cout << " Foos added..." << std::endl;
for (const auto& d : vector_Test) {
std::cout << "-----" << d.getVal() << "-----" << std::endl;
}
std::cout << " Foos printed..." << std::endl;
}
std::cout << " Foos out of scope..." << std::endl;
std::cout << "end!" << std::endl;
//
return 0;
}
I see the following output:
Con:
Con:
Con:
Foos created...
Des:
Des:
Des:
Foos added...
-----111-----
-----6555-----
------444-----
Foos printed...
Des:
Des:
Des:
Des:
Des:
Des:
Foos out of scope...
end!
so my question why are more objects destroyed as created?
I would expect an even number... if I create directly/ indirectly 3 objects then destroy 3 objects
Do I habe a memory leak some where?
thanks
Ps: my compiler is MinWG
When you do vector_Test.push_back(a); you are adding a copy of the instance to the vector.
Which means later on those copies and the original elements get destroyed.
Related
here is my code snippet:
#include <iostream>
#include <list>
#include <memory>
class A
{
public:
int a = 100;
A()
{
std::cout << "Create A" << std::endl;
}
~A()
{
std::cout << "Release A" << std::endl;
}
virtual void printer() = 0;
};
std::list<std::shared_ptr<A>> arr;
class B : public A
{
public:
int b = 1000;
~B()
{
std::cout << "Release B" << std::endl;
}
void printer() override
{
std::cout << "B's printer" << std::endl;
}
B()
{
std::shared_ptr<A> tmp(this);
arr.push_back(tmp);
(*arr.begin())->printer();
std::cout << "inside B's c'tor test B counts: " << tmp.use_count()
<< std::endl;
}
};
int main(int argc, char const *argv[])
{
std::shared_ptr<B> B_ptr = std::make_shared<B>();
std::shared_ptr<A> A_ptr(B_ptr);
std::cout << "list address: " << (*arr.begin()).get() << std::endl;
std::cout << "test B address: " << B_ptr.get() << std::endl;
std::cout << "test A address: " << A_ptr.get() << std::endl;
std::cout << "list counts: " << (*arr.begin()).use_count() << std::endl;
std::cout << "test B counts: " << B_ptr.use_count() << std::endl;
std::cout << "test A counts: " << A_ptr.use_count() << std::endl;
return 0;
}
My expectation is: A's reference count should be three, but only got 2. I think when I push_back to the list, there should be a temporarily created share_ptr object, even it is get destroyed, the one in list should also pointing to the same address as A_ptr and B_ptr. It turns out that they (those three), did pointing at the same address, but use_count got different results. (*arr.begin()).use_count() is 1, the others are both 2.
Why? Please help.
Ps: I know turning this pointer to share_ptr is stupid operation, but the result doesn't make sense and even disobey the syntax.
My expectation is: A's reference count should be three, but only got 2.
Your expectation is wrong. You only made one copy of the shared pointer, so the use count is 2.
std::shared_ptr<A> tmp(this);
On this line you transfer the ownership of a bare pointer that you don't own into a new shared pointer. Since this was already owned by another shared pointer, the behaviour of the program will be undefined when the two separate owners attempt to destroy it.
Creating a shared pointer from this is possible using std::enable_shared_from_this, but it's not simple.
After read Inside the C++ Object Model, I try to call member function from vptr.
I found the following situation by accident
gcc version 9.2.0 (tdm64-1)
#include <iostream>
class Foo;
Foo* foo;
class FooBase
{
public:
virtual void Bar1(){};
virtual void Bar2(){};
};
class Foo : FooBase
{
public:
void Bar1()
{
if (this == nullptr)
{
std::cout << "this == nullptr in Bar1" << std::endl;
}
else
{
std::cout << "this == " << this << " in Bar1" << std::endl;
std::cout << "foo == " << foo << " in Bar1" << std::endl;
}
std::cout << "Bar1" << std::endl;
}
};
int main()
{
foo = new Foo;
// std::cout << "foo == " << foo << " in main" << std::endl;
int* vptr = reinterpret_cast<int*>(foo);
int* bar1_ptr = reinterpret_cast<int*>(*vptr);
typedef void (*Func1)();
typedef void (*Func2)(Foo*);
Func1 bar10 = (Func1)*bar1_ptr;
Func2 bar11 = (Func2)*bar1_ptr;
bar10(); // sometimes 'this == 0xffffffff in Bar1'
bar11(nullptr); // this == nullptr in Bar1
return 1;
}
When I comment std::cout << "foo == " << foo << " in main" << std::endl;
the output is
this == 0x96ae0 in Bar1
foo == 0x96ae0 in Bar1
Bar1
this == nullptr in Bar1
Bar1
But when I uncomment std::cout << "foo == " << foo << " in main" << std::endl;
the output is
foo == 0x1d6ae0 in main
this == 0xffffffff in Bar1
foo == 0x1d6ae0 in Bar1
Bar1
this == nullptr in Bar1
Bar1
Q1: Why this pointer has a default value foo == this?
Q2: Why this pointer was changed after uncomment?
When you access Bar1 via Func1, this ends up being whatever was on the stack in the first arg's position. It wasnt a default value - it just happened to be there from your previous calls.
No surprise that the stack can change with change to previous calls.
As you probably found out, calling a class member functions can be implemented as a regular function that takes a class pointer as an argument. In your compiler and case, it looks as though the following are equivalent.
foo->Bar1();
bar11(foo);
Having some trouble with passing instances of objects around in other objects. In the end of the main application I want iDogClassOne and iDogClassTwo to reference the same object and I want that object to contain the numbers that were placed in variableA. What am I doing wrong here? The addresses of tempDogClass, iDogClassOne, and iDOgClassTwo are all different so I am pretty sure I am currently creating 3 instances of the dog class which I don't want to do..... Any help would be greatly appreciated.
class dogClass{
public:
void setVariableA(std::vector<double> newNum) {
variableA.push_back(newNum);
}
void printVariableA() {
if (variableA.size() != 0) {
std::cout << variableA[0][0] << std::endl;
std::cout << variableA[0][1] << std::endl;
}
}
dogClass &dogClass::operator=(const dogClass &src) {
variableA = src.variableA;
return *this;
}
private:
std::vector<std::vector<double>> variableA;
};
class animalClass{
public:
void addNumberToDog(std::vector<double> num) {
dogClass tempDogClass;
getDogOne(tempDogClass);
tempDogClass.setVariableA(num);
std::cout << "Address of temp Dog: " << &tempDogClass << std::endl;
std::cout << "Variables in tempDog:\n";
tempDogClass.printVariableA();
std::cout << std::endl;
}
void getDogOne(dogClass &dogOne) {
dogOne = dogs[0];
}
void setDogOne(dogClass &dogOne) {
dogs.push_back(dogOne);
}
private:
std::vector<dogClass> dogs;
};
int main() {
animalClass iAnimalClass;
dogClass iDogClassOne;
iAnimalClass.setDogOne(iDogClassOne);
std::vector<double> newNum;
newNum.push_back(12);
newNum.push_back(15);
iAnimalClass.addNumberToDog(newNum);
dogClass iDogClassTwo;
iAnimalClass.getDogOne(iDogClassTwo);
//Why are these not equal. Also why does dog Two not contain the values in dog One?
std::cout << "Address of dog One: " << &iDogClassOne << std::endl;
std::cout << "Variables in dog One:\n";
iDogClassOne.printVariableA();
std::cout << std::endl;
std::cout << "Address of dog Two: " << &iDogClassTwo << std::endl;
std::cout << "Variables in dog Two:\n";
iDogClassTwo.printVariableA();
std::cout << std::endl;
return 0;
}
output of console application (why does iDogClassOne and iDogClassTwo not contain the numbers? also why are tempDog, iDogClassOne, and iDogClassTwo not the same object?)
Address of temp Dog: 00000000002AF8A0
Variables in tempDog:
12
15
Address of dog One: 00000000002AF938
Variables in dog One:
Address of dog Two: 00000000002AF920
Variables in dog Two:
Because you are making copies of the dogClass objects in many places.
Please think about the difference of values, references and pointers.
For example in the main() function you call iAnimalClass.setDogOne(iDogClassOne); The argument is passed as reference, that is ok. But then you copy it into the vector. This is little bit tricky because you cannot pass the reference in a vector. In this case you will have to use a vector of pointers to dogClass.
Now you already have two instances of dogClass. One in the main function, another one in the vector of the animalClass.
The next problem is in the main() function where you instantiate iDogClassTwo.
Now you have three instances of dogClass.
Then you call iAnimalClass.getDogOne(iDogClassTwo); which copies the dog from the vector to the dog in the main function.
Here is the corrected Version:
#include <vector>
#include <iostream>
class dogClass{
public:
void setVariableA(std::vector<double> newNum) {
variableA.push_back(newNum);
}
void printVariableA() {
if (variableA.size() != 0) {
std::cout << variableA[0][0] << std::endl;
std::cout << variableA[0][1] << std::endl;
}
}
dogClass & operator=(const dogClass &src) {
variableA = src.variableA;
return *this;
}
private:
std::vector<std::vector<double>> variableA;
};
class animalClass{
public:
void addNumberToDog(std::vector<double> num) {
dogClass& tempDogClass = getDogOne();
tempDogClass.setVariableA(num);
std::cout << "Address of temp Dog: " << &tempDogClass << std::endl;
std::cout << "Variables in tempDog:\n";
tempDogClass.printVariableA();
std::cout << std::endl;
}
dogClass& getDogOne() {
return *dogs[0];
}
void setDogOne(dogClass &dogOne) {
dogs.push_back(&dogOne);
}
private:
std::vector<dogClass*> dogs;
};
int main() {
animalClass iAnimalClass;
dogClass iDogClassOne;
iAnimalClass.setDogOne(iDogClassOne);
std::vector<double> newNum;
newNum.push_back(12);
newNum.push_back(15);
iAnimalClass.addNumberToDog(newNum);
dogClass& iDogClassTwo = iAnimalClass.getDogOne();
//Why are these not equal. Also why does dog Two not contain the values in dog One?
std::cout << "Address of dog One: " << &iDogClassOne << std::endl;
std::cout << "Variables in dog One:\n";
iDogClassOne.printVariableA();
std::cout << std::endl;
std::cout << "Address of dog Two: " << &iDogClassTwo << std::endl;
std::cout << "Variables in dog Two:\n";
iDogClassTwo.printVariableA();
std::cout << std::endl;
return 0;
}
why does iDogClassOne and iDogClassTwo not contain the numbers?
int main()
{
animalClass iAnimalClass;
dogClass iDogClassOne;
iAnimalClass.setDogOne(iDogClassOne); // pushes a copy of iDogClassOne
// into a vector animalClass::dogs
std::vector<double> newNum;
newNum.push_back(12);
newNum.push_back(15);
iAnimalClass.addNumberToDog(newNum); // Only operates on function local variable
// variable tempDogClass without having
// any effect on the outside world.
dogClass iDogClassTwo;
iAnimalClass.getDogOne(iDogClassTwo); // copies the copy of iDogClassOne earlier pushed
// into the vector animalClass::dogs to iDogClassTwo
std::cout << "Address of dog One: " << &iDogClassOne << std::endl;
std::cout << "Variables in dog One:\n";
iDogClassOne.printVariableA();
std::cout << "\nAddress of dog Two: " << &iDogClassTwo << std::endl;
std::cout << "Variables in dog Two:\n";
iDogClassTwo.printVariableA();
}
why are tempDog, iDogClassOne, and iDogClassTwo not the same object?
Why are a, b and c not the same object in following example?
void func()
{
int c;
}
int main()
{
int a;
int b;
func();
}
I'm using Visual Studio 2017 and came across a bug which I cannot understand. I have this code as an example:
#include <iostream>
struct Foo
{
int a = 0;
int c;
int *b;
Foo(int n)
{
a = n;
b = &c;
}
};
struct Bar
{
Foo nestedFoo = Foo(0);
Bar(int n)
{
std::cout << "bar constructor nestedFoo before:" << std::endl;
std::cout << &nestedFoo.a << std::endl;
std::cout << nestedFoo.b << std::endl;
nestedFoo = Foo(n);
std::cout << "bar constructor nestedFoo after:" << std::endl;
std::cout << &nestedFoo.a << std::endl;
std::cout << nestedFoo.b << std::endl;
}
};
struct App
{
Bar bar = Bar(2);
};
int main()
{
App app;
Bar bar = Bar(10);
Foo foo = Foo(5);
std::cout << "foo before:" << std::endl;
std::cout << &foo.a << std::endl;
std::cout << foo.b << std::endl;
foo = Foo(20);
std::cout << "foo after:" << std::endl;
std::cout << &foo.a << std::endl;
std::cout << foo.b << std::endl;
std::cout << "bar.nestedFoo:" << std::endl;
std::cout << &bar.nestedFoo.a << std::endl;
std::cout << bar.nestedFoo.b << std::endl;
std::cout << "app.bar.nestedFoo:" << std::endl;
std::cout << &app.bar.nestedFoo.a << std::endl;
std::cout << app.bar.nestedFoo.b << std::endl;
return 0;
}
I expected the pointer and the address of the member to be the same after the reassignment but it seems this is not the case, &Foo.a and Foo.b have different values:
bar constructor nestedFoo before:
0058FEE8
0058FEE8
bar constructor nestedFoo after:
0058FEE8
0058FC24
bar constructor nestedFoo before:
0058FED8
0058FED8
bar constructor nestedFoo after:
0058FED8
0058FD04
foo before:
0058FEC8
0058FEC8
foo after:
0058FEC8
0058FDF8
bar.nestedFoo:
0058FED8
0058FD04
app.bar.nestedFoo:
0058FEE8
0058FC24
At first I thought it only happened when I had Foo as a member of another struct, but it seems to happen even at a top-level assignment. So what am I doing wrong?
Any help will be appreciated, thank you!
Edit: showing that assigning b to &c which is a member that doesn't get (explicitly) reassigned also doesn't work.
When running the following code, it seems that the destructor is running twice. I have a theory that this might have to do with an automatic move constructor being added, but I'm not sure how to test this.
#include <iostream>
#include <functional>
struct Structure {
Structure(int n) :
Value(n) {
std::cout << "constructor: " << Value << std::endl;
}
~Structure() {
std::cout << "destructor: " << Value << std::endl;
}
int Value;
};
int main() {
int Init = 4;
std::function<void()> Function = [Instance = Structure(Init)] () {
std::cout << "Value is: " << Instance.Value << std::endl;
};
Function();
Function();
return 0;
}
Output:
constructor: 4
destructor: 4
Value is: 4
Value is: 4
destructor: 4
Is this output correct?
std::function works by copying the callable object you provide. There is no copy-elision here, since your lambda is not an std::function but of an anonymous, unrelated type.
Hence, the two destructors you see are:
The Instance member of the original, temporary, lambda;
The Instance member of the copy of the lambda that was stored into the std::function and lived until the end of main.
Ok, I defined the move and copy constructors manually and also saw errors when I instructed the compiler to delete them in a variant of the code below. Everything seems normal.
Revised code:
#include <iostream>
#include <functional>
struct Structure {
Structure(int n) :
Value(n) {
std::cout << "constructor: " << Value << std::endl;
}
Structure(const Structure& other) :
Value(other.Value) {
std::cout << "copy constructor: " << Value << std::endl;
}
Structure(Structure&& other) :
Value(other.Value) {
other.Value = -1;
std::cout << "move constructor: " << Value << std::endl;
}
~Structure() {
std::cout << "destructor: " << Value << std::endl;
}
int Value;
};
int main() {
int Init = 4;
std::function<void()> Function = [Instance = Structure(Init)] () {
std::cout << "Value is: " << Instance.Value << std::endl;
};
Function();
Function();
return 0;
}
Output:
constructor: 4
move constructor: 4
destructor: -1
Value is: 4
Value is: 4
destructor: 4