为什么要调用dtor(使用annoymous / lambda func) [英] Why is the dtor being called (using annoymous/lambda func)

查看:173
本文介绍了为什么要调用dtor(使用annoymous / lambda func)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图模仿一个终于像一个效果。所以我想我应该运行一个快速脏的测试。

I am trying to mimic a finally like effect. So i thought i should run a quick dirty test.

这个想法是使用 Most Important const 停止销毁并将finally块放入lambda。然而显然我做错了,它在MyFinally()结束时被调用。我如何解决这个问题?

The idea was to use Most Important const to stop destruction and to put the finally block in a lambda. However apparently i did something wrong and its being called at the end of MyFinally(). How do i solve this problem?

#include <cassert>
template<typename T>
class D{
    T fn;
public:
    D(T v):fn(v){}
    ~D(){fn();}
};

template<typename T>
const D<T>& MyFinally(T t) { return D<T>(t); }

int d;
class A{
    int a;
public:
    void start(){
        int a=1;
        auto v = MyFinally([&]{a=2;});
        try{
            assert(a==1);
            //do stuff
        }
        catch(int){
            //do stuff
        }
    }
};
int main() {
    A a;
    a.start();
}

我的解决方案代码(注意:

My Solution code (Note: You can not have two finally in the same block. as expect. But still kind of dirty)

#include <cassert>
template<typename T>
class D{
    T fn; bool exec;
public:
    D(T v):fn(v),exec(true){}
    //D(D const&)=delete //VS doesnt support this yet and i didnt feel like writing virtual=0
    D(D &&d):fn(move(d.fn)), exec(d.exec) {
      d.exec = false;
    }

    ~D(){if(exec) fn();}
};
template<typename T>
D<T> MyFinally(T t) { return D<T>(t); }


#define FINALLY(v) auto OnlyOneFinallyPlz = MyFinally(v)

int d;
class A{
public:
    int a;
    void start(){
        a=1;
        //auto v = MyFinally([&]{a=2;});
        FINALLY([&]{a=2;});
        try{
            assert(a==1);
            //do stuff
        }
        catch(int){
            FINALLY([&]{a=3;}); //ok, inside another scope
            try{
                assert(a==1);
                //do other stuff
            }
            catch(int){
                //do other stuff
            }
        }
    }
};
void main() {
    A a;
    a.start();
    assert(a.a==2);
}



如果你删除&

Funny enough, if you remove the & in MyFinally in the original code it works -_-.

推荐答案

// WRONG! returning a reference to a temporary that will be
// destroyed at the end of the function!
template<typename T>
const D<T>& MyFinally(T t) { return D<T>(t); }

你可以解决我引入一个移动构造函数

You can fix it my introducing a move constructor

template<typename T>
class D{
    T fn;
    bool exec;

public:
    D(T v):fn(move(v)),exec(true){}

    D(D &&d):fn(move(d.fn)), exec(d.exec) {
      d.exec = false;
    }

    ~D(){if(exec) fn();}
};

然后你可以重写你的玩具

And then you can rewrite your toy

template<typename T>
D<T> MyFinally(T t) { return D<T>(move(t)); }

希望它有帮助。在使用 auto 时,不需要const引用技巧。有关如何执行此操作,请参见此处 C ++ 03与const引用。

Hope it helps. No "const reference" trick is needed when you work with auto. See here for how to do it in C++03 with const references.

这篇关于为什么要调用dtor(使用annoymous / lambda func)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆