当前位置:  开发笔记 > 编程语言 > 正文

返回值优化和析构函数调用

如何解决《返回值优化和析构函数调用》经验,为你挑选了1个好方法。

我知道RVO主要应用但我可以依靠吗?我有一个函数创建一个FlagContainer类的对象.

class FlagContainer {
public:
    ~FlagContainer() {
        someItem->flag = true;
    }
private:
    Item * someItem;
}

public FlagContainer createFlagContainer() {
    return FlagContainer();
}

在调用者使用容器之后,必须设置标志.所以我可以用析构函数做到这一点.

{
    FlagContainer container = createFlagContainer();
    // do something with container
}

超出范围时,将调用析构函数.但是我可以确定在createFlagContainer中永远不会调用析构函数吗?有没有办法实现这个目标?

我会使用AVR GCC 4.7.0编译器.



1> Richard Hodg..:

我知道RVO主要应用但我可以依靠吗?

不要依赖RVO来实现逻辑.简而言之,编译程序的人可以使用命令行选项将其关闭.

有没有办法实现这个目标?

令人惊讶的是,标准库已经为您提供了这一功能,因此您无需自行承担实施它的风险(移动构造函数和运算符非常难以正确实现)

std::unique_ptr 使用自定义删除器可以很好地完成工作.

#include 
#include 
#include 

// test type
struct X
{
    bool flag = false;
};


// a custom deleter that sets a flag on the target

struct flag_setter_impl
{
    template
    void operator()(X* px) const {
        if (px) {
            assert(!px->flag);
            std::cout << "setting flag!" << std::endl;
            px->flag = true;
        }
    }
};

// a type of unique_ptr which does not delete, but sets a flag
template
using flag_setter = std::unique_ptr;

// make a flag_stter for x

template
auto make_flag_setter(X& x) -> flag_setter
{
    return flag_setter(&x, flag_setter_impl());
}


// quick test

auto main() -> int
{
    using namespace std;

    X x;

    {
        auto fs1 = make_flag_setter(x);
        auto fs2 = move(fs1);
    }
    return 0;
}

但我的目标没有STL

然后不要忘记你的0,3,5规则

#include 
#include 
#include 

// test type
struct X
{
    bool flag = false;
};


// a custom deleter that sets a flag on the target

struct flag_setter_impl
{
    template
    void operator()(X* px) const {
        if (px) {
            assert(!px->flag);
            std::cout << "setting flag!" << std::endl;
            px->flag = true;
        }
    }
};

// a type of unique_ptr which does not delete, but sets a flag
template
struct flag_setter
{
    flag_setter(X* px) : px(px) {}
    flag_setter(const flag_setter&) = delete;
    flag_setter(flag_setter&& r) noexcept : px(r.px) { r.px = nullptr; }
    flag_setter& operator=(const flag_setter& r) = delete;
    flag_setter& operator=(flag_setter&& r)
    {
        flag_setter tmp(std::move(r));
        std::swap(tmp.px, px);
        return *this;
    }
    ~flag_setter() noexcept {
        flag_setter_impl()(px);
    }

private:
    X* px;
};

// make a flag_stter for x

template
auto make_flag_setter(X& x) -> flag_setter
{
    return flag_setter(&x);
}


// quick test

auto main() -> int
{
    using namespace std;

    X x;

    {
        auto fs1 = make_flag_setter(x);
        auto fs2 = move(fs1);
    }
    return 0;
}

推荐阅读
拾味湖
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有