Consider following code compiled under C++11 with gcc:
#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;
}
The program can be built without errors but an attempt to launch it is ignored or results in failure.
On Windows 10, launching the resulted exe file via command prompt just prints a blank line with no explanation, even though program should output Main called.
.
When running this in VS Code's integrated terminal I get somewhat better error message:
The terminal process "C:\WINDOWS\System32\cmd.exe /d /c {path to exe file} failed to launch (exit code: 3221226356).
When I change the Box definition to one that doesn't use a pointer for the box member it works:
class Box
{
char box[128];
public:
void example(int a, int b)
{
printf("%d %d", a, b);
}
};
What gives?
This is a combination of several arcane aspects of C++:
unordered_map<char, function<void(int, int)>> methods = {
{'a', bind(&Box::example, box, _1, 8)}
};
If you change this to:
unordered_map<char, function<void(int, int)>> methods = {
{'a', bind(&Box::example, &box, _1, 8)}
};
The code should still compile, and it will run without errors. Verified with gcc 10.
Your class Box
violates the Rule Of Three . If a Box
object gets copy-constructed there will be copies of a single Box
object with the same pointer, and when both of them get destroyed, an attempt will be made to delete
the same pointer multiple times. Hillarity ensues.
So that's the first factor that raised your issue: your class was not Rule Of 3 compliant.
The second issue is that std::bind
is quite versatile and has multiple overloads. The overload you used in your program effectively boils down that (as part of its inner workings) an internal copy of the box
object gets made, triggering the Rule Of 3 violation.
But std::bind
can also work here using a pointer to the object with the bound method, and this avoids the need to make a copy of it.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.