作为一个假设的问题,我想使用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; };
};
首先,我尝试使用auto
而不是明确指定函数类型,但我收到错误,说我无法在非静态字段中使用auto
。
这似乎确实有效,因为它显然产生了所需的行为。我用它来使用OpenGL绘制一些分形,所以最终做了一些相当密集的工作。
正如我所说,它似乎有用,我特别使用了引用捕获器,因为我认为因为this
是对当前实例的引用,所以可能需要它,并且为了获取者的值捕获默认情况下,标识符最终在类范围内搜索(在本例中)并查找字段。
我有两个问题:
我没有用visual studio测试过这个,但是我正在使用的是CLion和MSVC编译器,this
被突出显示为一个不存在的变量(即使它“有效”)。有什么想法会发生这种情况吗?
课程结束时很慢。因为在一个数量级以上慢。当我使用普通的getter和像double getRe() {return re;}
这样的setter时,渲染从绝对瞬间变为2-3秒。为什么会这样?
答案 0 :(得分:4)
我喜欢这个主意,但在实践中效果并不好。
std::function
是一个类类型,就像您可能编写的任何其他自定义类一样。 sizeof(std::function)
因实现而异,但合理的值为24
字节 1 。这意味着,对于要添加的每个成员24
,您要为sizeof(Complex)
添加std::function
个字节,而为每个成员函数添加0
个字节。与大多数计算机上的sizeof(double) == 8
相比,这是一个很大的开销:您的Complex
类型可能是16
个字节,而是大约112
个字节。
此外,每个std::function
成员都必须初始化,可能需要堆分配,并且由于类型擦除,调用std::function
涉及虚函数(或等效函数)。这使得编译器很难优化并且几乎不可能使编译器内联函数,而常规成员函数几乎可以保证内联,因为它们很简单。
将std::function
用于成员函数意味着您的类型无用大,初始化需要更多工作,并且更难以优化。这就是为什么它要慢得多。
1:目前,sizeof(std::function)
实际上32
字节,48
字节和libstdc++, libc++, and MSVC's STL respectively 上的64
字节
为了避免每个对象的开销,你可以有static constexpr
个成员(至少在C ++ 17中),但是你必须有一个明确的this
参数,它会删除所有成员函数有的好糖。您必须写Complex::getRe(myComplex)
而不是myComplex.getRe()
答案 1 :(得分:0)
让我为您修复此代码:
struct Complex {
double re, im;
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;
};
完全相同的结果,更好的可读性,更小的内存占用。去吧。对于const-correctness,你的代码也非常糟糕。
是的,由于多种因素,您的代码非常慢: