相关疑难解决方法(0)

C++:可以优化未使用的lambda显式捕获吗?

我有相当数量的代码,它依赖于捕获shared_from_this()当使用lambda表达式作为回调时确保我的实例保持活动状态:

std::shared_ptr<Thing> self = shared_from_this();
auto doSomething = [this, self] ()
{
    // various statements, none of which reference self, but do use this
}
Run Code Online (Sandbox Code Playgroud)

所以问题是:由于我没有self在lambda体内引用,是否允许一致的编译器优化捕获?


考虑以下程序:

#include <functional>
#include <iostream>
#include <memory>

std::function<void ()> gFunc;

struct S : std::enable_shared_from_this<S>
{
    void putGlobal()
    {
        auto self = shared_from_this();
        gFunc = [self] { };
    }
};

int main()
{
    auto x = std::make_shared<S>();
    std::cout << x.use_count() << std::endl;
    x->putGlobal();
    std::cout << x.use_count() << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

输出是:

1 …
Run Code Online (Sandbox Code Playgroud)

c++ lambda language-lawyer c++11

25
推荐指数
1
解决办法
2141
查看次数

总是在lambda表达式中捕获所有内容是不好的做法?

std::function<int()> void f1()
{
    int a, b, c, d, ..., x, y, z;

    return [=] { return a + b + c; };
}
Run Code Online (Sandbox Code Playgroud)

std::function<int()> void f2()
{
    int a, b, c, d, ..., x, y, z;

    return [a, b, c] { return a + b + c; };
}
Run Code Online (Sandbox Code Playgroud)

毋庸置疑,前者比后者更短,更方便,更优雅.

但是,我仍然担心:

从性能的角度来看,后者总是优于前者吗?

标准是否保证lambda表达式仅捕获必要的变量?即,在前一示例中,仅捕获a,b,c,未使用的变量d,...,x,y,z不是.

c++ performance lambda coding-style c++11

18
推荐指数
1
解决办法
5236
查看次数

强制C++ 11 lambda捕获变量

假设复制变量具有所需的副作用.我想声明一个复制变量但不使用该变量的lambda.这样做的最低要求是什么?

Copiable copyable;

auto lambda1 = [=](){};
auto lambda2 = [copyable](){};
auto lambda3 = [=](){ copyable; }
auto lambda4 = [=](){ volatile copy = copyable; }
Run Code Online (Sandbox Code Playgroud)

lambda1使用隐式捕获,并且由于正文没有提及copyable,我不相信它实际上是复制它.

lambda2使用显式捕获,似乎根据这个,它应该通过副本捕获.是否允许编译器删除副本?有关此问题的另一个讨论,请参阅

lambda3使用隐式捕获,但身体提到copyable.这是否构成了一种使用方式copyable

lambda4使用隐式捕获并强制另一个volatile副本.我确信这实际上会有效,但它的副本数量超过了最低限度.

激励案例:我需要在完成任意数量的lambda调用后运行清理,可能在不同的线程中.我可以通过使用一个std::shared_ptr运行清理的自定义删除器来实现这一点,并以某种方式将其传递给每个lambda.然后,当所有共享ptrs超出范围时,清理将运行.

编辑:lambda3并且lambda4错过了=隐式捕获.

c++ lambda c++11

7
推荐指数
1
解决办法
1329
查看次数

什么时候更喜欢lambda中的显式捕获而不是隐式捕获?

有时我会std::find_if在本地函数中执行(例如)具有5个局部变量(包括参数)的情况.但是,传入STL算法的lambda只需要访问其中的1个.我可以通过以下两种方式之一来捕获它:

void foo(int one, int two, int three)
{
    std::vector<int> m_numbers;
    int four, five;

    std::find_if(m_numbers.begin(), m_numbers.end(), [=](int number) {
        return number == four;
    });
}
Run Code Online (Sandbox Code Playgroud)

或者我可以这样做:

void foo(int one, int two, int three)
{
    std::vector<int> m_numbers;
    int four, five;

    std::find_if(m_numbers.begin(), m_numbers.end(), [four](int number) {
        return number == four;
    });
}
Run Code Online (Sandbox Code Playgroud)

(注意我没有编译此代码,对任何语法错误或其他错误道歉)

我知道隐式捕获是基于odr使用的规则,所以在功能和实现方面,我认为两者都是相同的.什么时候使用显式捕获而不是隐式捕获?我唯一的想法与封装原则有些相关:只能访问所需的东西,编译器可以帮助您确定何时访问变量.它还保持方法的本地状态(它的不变量,在执行期间函数的生命周期)更安全.但这些真的是实际问题吗?

是否存在使用显式捕获而不是隐式捕获的功能性原因?遵循什么是好的经验法则或最佳做法?

c++ lambda c++11

7
推荐指数
2
解决办法
1489
查看次数

C++ 动态加载类:为什么需要“销毁”函数?

这一页检查并给出了如何动态加载和使用类的非常清晰的示例,但有一些我很难理解的内容:

我明白为什么需要“创建”功能,但为什么需要“销毁”功能?为什么没有将接口析构函数声明为纯虚拟函数?

我做了一个相同的例子,除了:

~polygon() = 0;
Run Code Online (Sandbox Code Playgroud)

的析构函数triangle是:

triangle::~triangle() {
    std::cout << "triangle Dtor is called" <<std::endl;
}
Run Code Online (Sandbox Code Playgroud)

然后当我使用时:

delete poly;
Run Code Online (Sandbox Code Playgroud)

该消息确实显示(Linux 下的 GCC 5.4.0)。

我试图寻找其他示例,但它们都提到并使用“销毁”函数,没有使用简单的纯虚拟析构函数的示例,这使我相信我在这里遗漏了一些东西,所以..它是什么?

不想使用销毁函数的背景是我想在 a 中使用分配的对象shared_ptr并且以后不关心它的生命周期,使用“销毁”函数会很棘手,因此我需要知道是否有必要。

c++ memory-management dynamic-loading dlopen

4
推荐指数
1
解决办法
1287
查看次数