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
Related
The following class outputs when a constructor is called:
class A {
public:
A() {
std::cout << "Default Constructor called at address:" << this << "!\n";
}
A(int val) : val_(val) {
std::cout << "Secondary Constructor called at address:" << this << "\n";
}
A(A&& other) : val_(std::move(other.val_)) {
std::cout << "Move constructor called from " << &other << " to " << this << "\n";
}
A& operator=(A&& other) {
std::cout << "Move assignment called from " << &other << " to " << this << "\n";
val_ = std::move(other.val_);
return *this;
}
private:
int val_;
};
This union allows me to skip the default constructor of A, which is desirable:
union MyUnion {
MyUnion() {}
A a;
};
My goal with main was to move-construct a. Instead it move-assigns the a.
int main(){
MyUnion my_union[2];
std::cout << "Entering for loop:\n";
for (int i = 0; i < 2; ++i){
my_union[i].a = std::move(A(i));
}
return 0;
}
An example output from the above main function is:
Entering for loop:
Secondary Constructor called at address:0x7ffcdd3553a8
Move assignment called from 0x7ffcdd3553a8 to 0x7ffcdd3553b0
Secondary Constructor called at address:0x7ffcdd3553a8
Move assignment called from 0x7ffcdd3553a8 to 0x7ffcdd3553b4
I wanted to move-construct, but I'm instead move-assigning. Move-assigning without move constructing is unsafe in general. The solution I came up with was to use std::construct_at. I also added a destructor. The full program with these modifications is below:
#include <iostream>
#include <memory>
#include <utility>
class A {
public:
A() {
std::cout << "Default Constructor called at address:" << this << "!\n";
}
A(int val) : val_(val) {
std::cout << "Secondary Constructor called at address:" << this << "\n";
}
A(A&& other) : val_(std::move(other.val_)) {
std::cout << "Move constructor called from " << &other << " to " << this << "\n";
}
A& operator=(A&& other) {
std::cout << "Move assignment called from " << &other << " to " << this << "\n";
val_ = std::move(other.val_);
return *this;
}
~A() {
std::cout << "Destructor called at " << this << "\n";
}
private:
int val_;
};
union MyUnion {
MyUnion() {
std::cout << "MyUnion Constructor called!\n";
}
void ConstructAt(A&& other){
std::construct_at(&a, std::forward<A>(other));
}
A a;
~MyUnion(){
std::cout << "MyUnion Destructor called!\n";
a.~A();
}
};
int main(){
MyUnion my_union[2];
std::cout << "\nEntering for loop:\n";
for (int i = 0; i < 2; ++i){
my_union[i].ConstructAt(std::move(A(i)));
}
std::cout << "\nExiting for loop:\n";
return 0;
}
This gives output:
MyUnion Constructor called!
MyUnion Constructor called!
Entering for loop:
Secondary Constructor called at address:0x7ffe38dd4838
Move constructor called from 0x7ffe38dd4838 to 0x7ffe38dd4840
Destructor called at 0x7ffe38dd4838
Secondary Constructor called at address:0x7ffe38dd4838
Move constructor called from 0x7ffe38dd4838 to 0x7ffe38dd4844
Destructor called at 0x7ffe38dd4838
Exiting for loop:
MyUnion Destructor called!
Destructor called at 0x7ffe38dd4844
MyUnion Destructor called!
Destructor called at 0x7ffe38dd4840
This appears to be what I want.
Question
Was this the correct way to call the move constructor? Am I using std::forward correctly? Is this the correct way to handle the destructor of a union?
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'd like to take out members of a temporary without unnecessary moving or copying.
Suppose I have:
class TP {
T _t1, _t2;
};
I'd like to get _t1, and _t2 from TP(). Is it possible without copying/moving members?
I've tried with tuples and trying to "forward" (I don't think it's possible) the members, but the best I could get was a move, or members dying immediately.
In the following playground using B::as_tuple2 ends up with members dying too soon, unless the result is bound to a non-ref type, then members are moved. B::as_tuple simply moves is safe with auto on client side.
I suppose this should be technically possible, since the temporary dies immediately, and the member do die while they could bound to variables on the calling site (Am I wrong?), and structured binding of a similar struct works as intended.
Is it possible to extend/pass life of the member onto an outside variable, or elide the move/copy? I need it with c++14 version, but I couldn't get it to work on c++17 either, so I am interested in both.
Playground:
#include <tuple>
#include <iostream>
using std::cout;
class Shawty {
/**
* Pronounced shouty.
**/
public:
Shawty() : _id(Shawty::id++) {cout << _id << " ctor\n"; }
Shawty(Shawty && s) : _id(Shawty::id++) { cout << _id << " moved from " << s._id << "\n"; }
Shawty(const Shawty & s) : _id(Shawty::id++) { cout << _id << " copied from " << s._id << "\n"; }
Shawty& operator=(Shawty && s) { cout << _id << " =moved from " << s._id << "\n"; return *this;}
Shawty& operator=(Shawty & s) { cout << _id << " =copied from " << s._id << "\n"; return *this;}
~Shawty() {cout << _id << " dtor\n"; }
int _id;
static int id;
};
int Shawty::id = 0;
class B {
public:
auto as_tuple() && {return std::make_tuple(std::move(_s1), std::move(_s2));}
auto as_tuple2() && {return std::forward_as_tuple(std::move(_s1), std::move(_s2));}
private:
Shawty _s1, _s2;
};
struct S {
Shawty _s1, _s2;
};
int main() {
std::cout << "----------\n";
auto [s1, s2] = B().as_tuple2();
std::cout << "---------\n";
auto tpl1 = B().as_tuple2();
std::cout << "----------\n";
std::tuple<Shawty, Shawty> tpl2 = B().as_tuple2();
std::cout << "----------\n";
std::cout << std::get<0>(tpl1)._id << '\n';
std::cout << std::get<1>(tpl1)._id << '\n';
std::cout << std::get<0>(tpl2)._id << '\n';
std::cout << std::get<1>(tpl2)._id << '\n';
std::cout << s1._id << '\n';
std::cout << s2._id << '\n';
std::cout << "--struct--\n";
auto [s3, s4] = S{};
std::cout << s3._id << '\n';
std::cout << s4._id << '\n';
std::cout << "----------\n";
return 0;
}
No. It is not possible to extend the lifetime of more than one member beyond the lifetime of the super object.
So, the only way to "get" members without copying is to keep the super object alive, and refer to them:
// member function
auto as_tuple3() & {
return std::make_tuple(std::ref(_s1), std::ref(_s2));
}
// usage
B b;
auto [s1, s2] = b.as_tuple3();
An example of extending lifetime of the object by binding a reference to a single member. Note that this requires the member to be accessible from where the reference is bound (not the case in your example, where the member is private):
auto&& s1 = B{}._s1;
Add support for structured binding to your B type.
class B {
public:
template<std::size_t I, class Self,
std::enable_if_t< std::is_same_v<B, std::decay_t<Self>>, bool> = true
>
friend constexpr decltype(auto) get(Self&& self) {
if constexpr(I==0)
{
using R = decltype(std::forward<Self>(self)._s1)&&;
return (R)std::forward<Self>(self)._s1;
}
else if constexpr(I==1)
{
using R = decltype(std::forward<Self>(self)._s2)&&;
return (R)std::forward<Self>(self)._s2;
}
}
private:
Shawty _s1, _s2;
};
namespace std {
template<>
struct tuple_size<::B>:std::integral_constant<std::size_t, 2> {};
template<std::size_t N>
struct tuple_element<N, ::B>{using type=Shawty;};
}
Test code:
int main() {
std::cout << "----------\n";
{
auto&& [s1, s2] = B();
}
}
output:
----------
0 ctor
1 ctor
1 dtor
0 dtor
Live example.
This is the best I can do. Note that s1 and s2 are references into a lifetime-extended version of B.
I am using "emplace" method to avoid memory copy.
But, when I am using the "emplace" inside a Lambda function. It always call implicit move constructor.
How I can avoid memory copy inside a Lambda function?
This sample program should not print “I am being moved.”
#include <vector>
#include <iostream>
struct A
{
int a;
A(int t) : a(t)
{
std::cout << "I am being constructed.\n";
}
A(A&& other) : a(std::move(other.a))
{
std::cout << "I am being moved.\n";
}
};
std::vector<A> g_a;
int main()
{
std::cout << "emplace_back:\n";
g_a.emplace_back(1);
std::cout << "emplace_back in lambda:\n";
auto f1 = [](int x) { g_a.emplace_back(x); };
f1(2);
std::cout << "\nContents: ";
for (A const& t : g_a)
std::cout << t.a << " ";
std::cout << std::endl;
}
It's not about the lambda function but rather about the vector that reallocates its memory. You can ammend this with std::vector::reserve.
int main() {
g_a.reserve(10);
^^^^^^^^^^^^^^^^
std::cout << "emplace_back:\n";
g_a.emplace_back(1);
std::cout << "emplace_back in lambda:\n";
auto f1 = [](int x) { g_a.emplace_back(x); };
f1(2);
std::cout << "\nContents: ";
for (A const& t : g_a)
std::cout << t.a << " ";
std::cout << std::endl;
}
Live Demo
I want to write a library wrapper class (LibWrap) around a C library that uses malloc/free. To do this I want to use C++'s RAII to allocate and free memory. I used lib_address as a random example address that I would receive from the library. However when defining my memeber variable the destructor that is called somehow has this lib_address.
I would expect the destructor of the member variable created by the default constructor not to know the new address that I am putting into the constructor of my replacement member variable.
#include <stdlib.h>
#include <iostream>
using namespace std;
class LibWrap
{
int j;
int lib_address;
public:
LibWrap(): //default LibWrap
j(0),
lib_address(0)
{
cout << "default LibWrap "<<j <<"\t\t"<<lib_address << "\t" << this<<endl;
}
LibWrap(int f_j): //special LibWrap
j(0),
lib_address(0)
{
j = f_j;
lib_address = rand();
cout << "special LibWrap " << j<<"\t"<< lib_address<< "\t" << this <<endl;
}
~LibWrap()
{
cout << "killing LibWrap " << j<<"\t" <<lib_address <<"\t" << this<< endl;
}
int g()
{
return j;
}
};
class A
{
int i;
LibWrap b;
public:
A(): //default A
i(0)
{
cout << "default A\t"<<i << endl;
}
A(int f_i)://special A
i(0)
{
i = f_i;
cout << "special A\t"<<i << endl;
b = LibWrap(10);
}
~A()
{
cout << "killing A\t"<<i << endl;
}
void p()
{
cout <<"Test values: "<< i<< "," << b.g() << endl;
}
};
int f()
{
//A a; a.p();
cout << "variable\t\tlib_address\treal_address" << endl;
A a = A(1);
cout << "End" << endl;
//a.p();
}
int main()
{
f();
}
Running this code I would expect to get the following result:
variable lib_address real_address
default LibWrap 0 0 0xbfef2e28
special A 1
special LibWrap 10 1804289383 0xbfef2df8
killing LibWrap 10 1804289383 0xbfef2df8 --would expect kiling LibWrap 0 0 0xbfef2e28
End
killing A 1
killing LibWrap 10 1804289383 0xbfef2e28 --would expect killing LibWrap 10 1804289383 0xbfef2df8
b = LibWrap(10);
This does not initialize b. b has already been initialized as part of constructing A. What you're doing is creating a temporary LibWrap and copying that temporary into b. Then, you're destroying that temporary LibWrap (which is where the extra destructor call with the lib_address comes from).
The temporary LibWrap is where the "0xbfef2df8" address comes from. The b variable is the "0xbfef2e28" address. That's why you're getting them in that order.