C ++:优化析构函数调用 [英] C++: Optimizing out destructor call

查看:104
本文介绍了C ++:优化析构函数调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这里有一个小代码示例:

There is a little code example here:

struct Data {
};

struct Init {
    Data *m_data;

    Init() : m_data(new Data) { }
    ~Init() {
        delete m_data;
    }
};

class Object {
    private:
        int m_initType;
        Data *m_data;
    public:
        Object(const Init &init) : m_initType(0), m_data(init.m_data) { }
        Object(Init &&init) : m_initType(1), m_data(init.m_data) { init.m_data = nullptr; }
        ~Object() {
            if (m_initType==1) {
                delete m_data;
            }
        }
};

对象可以通过两种方式初始化:

Object can be initialized two ways:


  • const Init& :此初始化只是将m_data存储为指针,m_data 拥有,所以〜 Object()无需执行任何操作(在这种情况下,m_data将在〜Init()处销毁)

  • Init&& :此初始化会转让m_data的所有权,对象成为m_data的所有者,因此〜Object()需要销毁它

  • const Init &: this initialization just stores m_data as a pointer, m_data is not owned, so ~Object() doesn't have to do anything (in this case, m_data will be destroyed at ~Init())
  • Init &&: this initialization transfers ownership of m_data, Object becomes the owner of m_data, so ~Object() needs to destroy it

现在,有一个函数:

void somefunction(Object object);

此函数在callInitA和callInitB中调用:

This function is called in callInitA and callInitB:

void callInitA() {
    Init x;
    somefunction(x); // calls the "const Init &" constructor
}

void callInitB() {
    somefunction(Init()); // calls the "Init &&" constructor
}

现在,这是我要完成的工作:在callInitA案例中,我想让编译器优化生成的临时 Object 的析构函数调用( Object 经常使用,并且我想减小代码大小)

Now, here's what I'd like to accomplish: in the callInitA case, I'd like to make the compiler to optimize away the destructor call of the resulting temporary Object (Object is used frequently, and I'd like to decrease code size).

但是,编译器并没有对其进行优化(已通过GCC和clang测试)。

However, the compiler doesn't optimize it away (tested with GCC and clang).

<设计了strong> Object ,因此它没有任何更改m_initType的函数,因此编译器将能够发现,如果在构造时将m_initType设置为0,则它​​不会改变,因此在

Object is designed so it doesn't have any functions which alter m_initType, so the compiler would be able to find out that if m_initType is set to 0 at construct time, then it won't change, so at the destructor it is still be 0 -> no need to call destructor at all, as it would do nothing.

甚至,m_initType也是 Object的不必要成员:仅在销毁时需要。

Even, m_initType is an unnecessary member of Object: it is only needed at destruct time.

您对如何实现此目标有任何设计想法吗?

Do you have any design ideas how to accomplish this?

更新:我的意思是说,使用某种C ++结构t(帮助程序类,等等)。 C ++是一门功能强大的语言,也许可以用某种C ++技巧来做到这一点。

UPDATE: I mean that using some kind of c++ construct (helper class, etc.). C++ is a powerful language, maybe with some kind of c++ trickery this can be done.

(我最初的问题比这个简化的问题更为复杂:对象可以使用其他类型的Init结构,但所有Objects构造函数都归结为以某种方式获取 Data *)

(My original problem is more complex that this simplified one: Object can be initialized with other kind of Init structures, but all Objects constructors boils down to getting a "Data*" somehow)

推荐答案

void callInitA() {
    Init x;
    somefunction(x); // calls the "const Init &" constructor
}

x Init 的内容如何,​​都无法优化c>。这样做会违反语言的设计。

The destruction of x cannot be optimized away, regardless of the contents of Init. Doing so would violate the design of the language.

不仅仅是 Init 是否包含资源的问题。与所有对象一样, Init x 将在堆栈上分配以后需要清理的空间,作为其中的隐式(不是您自己编写的代码的一部分)部分。析构函数。

It's not just a matter of whether Init contains resources or not. Init x, like all objects, will allocate space on the stack that later needs to be cleaned up, as an implicit (not part of code that you yourself write) part of the destructor. It's impossible to avoid.

如果意图是将 x 用作的对象somefunction 可以调用而不必重复创建和删除对 x 的引用,您应该像这样处理它:

If the intention is for x to be an object that somefunction can call without having to repeatedly create and delete references to x, you should be handling it like this:

void callInitA(Init & x) { //Or Init const& x
    somefunction(x); // calls the "const Init &" constructor
}

其他一些注意事项:


  • 确保您实施五规则(有时称为三元法则)在拥有资源的任何对象上。

  • 您可以考虑将所有指针包装在内std :: unique_ptr ,因为您似乎不需要 std :: unique_ptr 提供的功能。

  • Make sure you implement the Rule of Five (sometimes known as Rule of Three) on any object that owns resources.
  • You might consider wrapping all pointers inside std::unique_ptr, as it doesn't seem like you need functionality beyond what std::unique_ptr offers.

这篇关于C ++:优化析构函数调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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