考虑使用 gcc 在 C++11 下编译的以下代码:
#include <cstdio>
#include <functional>
#include <unordered_map>
using namespace std;
using namespace std::placeholders;
class Box
{
char* box;
public:
Box(): box(new char[128]) {}
~Box()
{
delete[] this->box;
}
void example(int a, int b)
{
printf("%d %d", a, b);
}
};
Box box;
unordered_map<char, function<void(int, int)>> methods = {
{'a', bind(&Box::example, box, _1, 8)}
};
int main()
{
fputs("Main called.", stdout);
return 0;
}
该程序可以无错误地构建,但尝试启动它会被忽略或导致失败。在 Windows 10 上,通过命令提示符启动生成的 exe 文件只会打印一个没有解释的空行,即使程序应该输出
Main called.
.在 VS Code 的集成终端中运行它时,我会收到更好的错误消息:
The terminal process "C:\WINDOWS\System32\cmd.exe /d /c {path to exe file} failed to launch (exit code: 3221226356).
当我将 Box 定义更改为不使用 box 成员指针的定义时,它可以工作:class Box
{
char box[128];
public:
void example(int a, int b)
{
printf("%d %d", a, b);
}
};
是什么赋予了?
最佳答案
这是 C++ 几个神秘方面的组合:
unordered_map<char, function<void(int, int)>> methods = {
{'a', bind(&Box::example, box, _1, 8)}
};
如果您将其更改为:unordered_map<char, function<void(int, int)>> methods = {
{'a', bind(&Box::example, &box, _1, 8)}
};
代码应该仍然可以编译,并且可以正常运行。使用 gcc 10 验证。您的类(class)
Box
violates the Rule Of Three .如果一个 Box
对象被复制构造,将有单个 Box
的拷贝具有相同指针的对象,当它们都被销毁时,将尝试 delete
同一个指针多次。希拉里随之而来。所以这是引发您问题的第一个因素:您的类(class)不符合 Rule Of 3。
第二个问题是
std::bind
非常通用,并且有多个重载。您在程序中使用的重载有效地归结为(作为其内部工作的一部分)box
的内部拷贝。对象被制造,触发违反规则 3。但是
std::bind
也可以在这里使用指向具有绑定(bind)方法的对象的指针,这避免了复制它的需要。
关于c++ - 使用绑定(bind)方法的程序已构建但无法启动,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63947848/