gpt4 book ai didi

c++ - 通过 lambda 调用成员函数时意外未初始化的数据

转载 作者:行者123 更新时间:2023-11-30 05:14:47 35 4
gpt4 key购买 nike

考虑以下短程序。我正在使用 std::function 和 lambda 将成员函数对象 (initialise) 设置为成员函数 (initialiser)类(A)。 initialise() 然后在 4 个地方被调用:1. 在 mainA 的构造函数中,2. 直接从 main ,3. 在 A 的构造函数中来自 B 的构造函数,以及 4. 直接来自 B 的构造函数。

    #include <iostream>
#include <functional>
#include <vector>

class A {
public:
A(std::vector<int> const& sizes) : m_sizes(sizes) {
set_initialiser();
initialise();
}
A() = default;
std::function<void()> initialise;
void set_initialiser() { initialise = [this]() {return initialiser(); }; };
// void set_initialiser() { initialise = std::bind(&A::initialiser, this); }; // the same occurs if I use bind instead of a lambda

private:
std::vector<int> m_sizes;
void initialiser() {
std::cout << "m_sizes size = " << m_sizes.size() << ", with contents:";
for (auto & s : m_sizes)
std::cout << " " << s;
std::cout << std::endl;
};
};

class B {
public:
B(std::vector<int> const& v) {
a = A(v);
a.initialise(); // here a.m_sizes and a.initialise.functor.this.m_sizes differ
};
private:
A a;
};

int main(int argc, char* argv[])
{
auto a = A({ 4,3,2,1 });
a.initialise();
auto b = B({ 4,3,2,1 });
return 0;
}

编译并运行此代码会出现以下意外(至少对我而言)的行为。

m_sizes size = 4, with contents: 4 3 2 1                                                                                
m_sizes size = 4, with contents: 4 3 2 1
m_sizes size = 4, with contents: 4 3 2 1
m_sizes size = 0, with contents:

谁能解释为什么最后一次调用 initialise() 包含未初始化的 m_sizes?我怀疑这一定与 lambda 中使用的 this 的不同实例有关,但我不明白为什么从 main 调用它应该有任何区别并从另一个类调用它。

最佳答案

a = A(v);

这一行创建了一个临时对象A(v)(我称它为t),并将其数据复制到at.initialise 包含一个 lambda,它按值捕获了 this(即 &t)。然后将此 lambda 复制到 a.initialise;但是请注意,它仍然引用 &t

然后,完整的表达式结束,t 被销毁(因为它是临时的),a.initialise 中捕获的指针现在悬空。下一次调用 a.initialise() 会解除对悬垂指针的引用,从而产生未定义的行为。

请注意,完全相同的问题(相同的未定义行为)也发生在您的 main 中,但其效果不同。以下是对原因的推测,但请记住,未定义的行为是未定义的,任何事情都可能发生。

我假设在 main 内部,发生了复制省略,并且临时 A({ 4,3,2,1 }) 直接在 的空间中构造>a,使其 thisa 相同,这使得对 initialise 的调用仍然有效。

B 的构造函数中,复制省略是不可能的(因为你正在做赋值而不是初始化),所以临时对象确实被销毁了,留下了一个正确销毁的 vector ,它恰好仍然与您的情况下的空 vector 相同(可能是因为它已从临时移动到 a)。

再次声明:这只是猜测,代码完全错误。

关于c++ - 通过 lambda 调用成员函数时意外未初始化的数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43292919/

35 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com