C++ lambdas作为类方法

Rar*_*ima 6 c++ methods performance lambda class

作为一个假设的问题,我想使用lambdas作为类方法.我知道这在专业背景下很糟糕,但无论如何我很好奇.一个例子可能最适合展示我想做的事情.这是复数的基本类:

class Complex {
    private:
        double re, im;
    public:
        Complex() : re(0.0), im(0.0) {}
        Complex(double re, double im) : re(re * 1.0), im(im * 1.0) {}
        Complex(const Complex &c) = default;

        ~Complex() = default;

        function<double(void)> getRe = [=]() -> double { return re; };
        function<void(double)> setRe = [&](double re) -> void { this->re = re; };

        function<double(void)> getIm = [=]() -> double { return im; };
        function<void(double)> setIm = [&](double im) -> void { this->im = im; };

};
Run Code Online (Sandbox Code Playgroud)

起初我尝试使用auto而不是显式指定函数类型但我得到错误说我不能auto在非静态字段中使用.

这似乎确实有效,因为它显然产生了所需的行为.我用它来使用OpenGL绘制一些分形,所以最终做了一些相当密集的工作.

正如我所说它似乎工作,我已经使用了参考捕获的特别是因为我认为,因为我this是可能需要的当前实例的引用,以及getter的值捕获,因为默认情况下标识符最终搜索(在这种情况)在类范围内找到字段.

我有两个问题:

  1. 我没有用visual studio测试过这个,但是我正在使用的是CLion和MSVC编译器,它this被强调为一个不存在的变量(即使它"有效").任何想法为什么会这样?

  2. 班级最终变得缓慢.因为在一个数量级以上慢.当我使用简单的getter和setter时,渲染从绝对瞬间变为double getRe() {return re;}2-3秒.为什么会这样?

Jus*_*tin 7

我喜欢这个想法,但在实践中效果并不好。

std::function是一个类类型,就像您可能编写的任何其他自定义类一样。sizeof(std::function)因实现而异,但合理的值为24bytes 1。这意味着与为每个成员函数添加24字节相比,您需要为要添加的每个成员添加字节。与大多数机器相比,这是很大的开销:您的类型可能是字节,但实际上是大致字节。sizeof(Complex)std::function0sizeof(double) == 8Complex16112

此外,每个std::function成员都必须初始化,可能需要堆分配,并且std::function由于类型擦除,调用 a 涉及虚拟函数(或等效函数)。这使得编译器很难优化,并且编译器几乎不可能内联函数,而常规成员函数由于非常简单,几乎可以保证被内联。

使用std::function成员函数意味着您的类型无用地更大,需要更多的工作来初始化,并且更难以优化。这就是为什么它慢得多。

1:此时,sizeof(std::function)实际上分别是libstdc++、libc++、MSVC的STL32上的bytes、48bytes、64bytes


为了避免每个对象的开销,您可以拥有static constexpr成员(至少在 C++17 中),但随后您必须拥有一个显式this参数,这会消除成员函数所具有的所有好处。你必须写Complex::getRe(myComplex)而不是myComplex.getRe()