以下代码根据我的理解不起作用。当Raise
调用handler对象的方法,随机(我假设未初始化的变量)值被打印。我怀疑map::insert
中的CreateTests
次调用导致某种移动导致this
参数无效,提供给std::function
提供给EventCoordinator::Register
的对象}}。该程序的预期输出将是在控制台中打印的2行,其值为0
& 1
已打印。有人可以告诉我这里的错误是什么吗?
#include <map>
#include <functional>
#include <vector>
#include <iostream>
class EventCoordinator
{
using Handler = std::function<void()>;
using Handlers = std::vector<Handler>;
std::map<int, Handlers> HandlerMap;
public:
void Register(const int id, std::function<void()> handler)
{
HandlerMap[id].emplace_back(handler);
}
void Raise(const int id)
{
try {
auto handlers = HandlerMap.at(id);
for (const auto& handler : handlers) {
handler();
}
}
catch (std::exception& e) {
std::cout << e.what();
}
}
};
class test
{
public:
test() : mId(-1)
{
std::cout << "test default constructor\n";
}
test(const int id, EventCoordinator& handler) : mId(id)
{
handler.Register(mId, std::bind(&test::func, *this));
}
void other()
{
std::cout << this << '\n';
}
void func() const
{
std::cout << this <<'\n';
std::cout << mId << '\n';
}
~test() = default;
test(const test& other) = default;
test(test&& other) noexcept = default;
test& operator=(const test& other) = default;
test& operator=(test&& other) noexcept = default;
int mId;
};
std::map<int, test> CreateTests(EventCoordinator& handler)
{
auto returnMap = std::map<int, test>();
returnMap.emplace(std::make_pair(0, test(0, handler)));
returnMap.emplace(std::make_pair(1, test(1, handler)));
return returnMap;
}
int main(int argc, char** args)
{
EventCoordinator handler;
auto ret = CreateTests(handler);
handler.Raise(0);
ret[0].other();
handler.Raise(1);
ret[1].other();
std::cin.get();
}
答案 0 :(得分:1)
在此功能中:
std::map<int, test> CreateTests(EventCoordinator& handler)
{
auto returnMap = std::map<int, test>();
returnMap.insert({ 0, test(0, handler)});
returnMap.insert({ 1, test(1, handler)});
return returnMap;
}
您创建了两个临时test
类。当CreateTests
返回时,这些超出了范围。
在main()
,
auto ret = CreateTests(handler);
handler.Raise(0);
handler.Raise(1);
调用 func
,访问test::mId
,但不再存在,因此值已损坏。
答案 1 :(得分:1)
根据@alain的建议,无法在test
对象的构造函数中执行test
对象的注册。 register_test
类中添加了test
方法。以下代码采用初始化的std::map<int,test>
对象,并对存储在地图中的对象调用test::register
。
#include <map>
#include <functional>
#include <vector>
#include <iostream>
#include <memory>
class EventCoordinator
{
using Handler = std::function<void()>;
using Handlers = std::vector<Handler>;
std::map<int, Handlers> HandlerMap;
public:
void Register(const int id, std::function<void()> handler)
{
HandlerMap[id].emplace_back(handler);
}
void Raise(const int id)
{
try {
auto handlers = HandlerMap.at(id);
for (const auto& handler : handlers) {
handler();
}
}
catch (std::exception& e) {
std::cout << e.what();
}
}
};
class test
{
int mId;
public:
test() : mId(-1)
{
std::cout << "test default constructor\n";
}
test(const int id) : mId(id)
{}
void register_test(EventCoordinator& handler) {
handler.Register(mId, std::bind(&test::func, this));
}
void func() const
{
std::cout << mId << '\n';
}
~test() = default;
test(const test& other) = default;
test(test&& other) noexcept = default;
test& operator=(const test& other) = default;
test& operator=(test&& other) noexcept = default;
};
void RegisterTests(std::map<int,test>& testCollection,EventCoordinator& coordinator)
{
for (auto& test: testCollection){
test.second.register_test(coordinator);
}
}
std::map<int, test> CreateTests(EventCoordinator& coordinator)
{
auto returnMap = std::map<int, test>();
returnMap.emplace(std::make_pair(0, test(0)));
returnMap.emplace(std::make_pair(1, test(1)));
RegisterTests(returnMap, coordinator);
return returnMap;
}
int main(int argc, char** args)
{
EventCoordinator handler;
auto ret = CreateTests(handler);
handler.Raise(0);
handler.Raise(1);
std::cin.get();
}
答案 2 :(得分:0)
经过几次尝试后,我发现了一个小错误。
在Register
构造函数中使用Test
成员函数时,使用指针this
,但是需要引用而不是指针,因此更改this
*this
我觉得代码运行正常:
test ( const int id , EventCoordinator& handler ) : mId ( id )
{
handler.Register ( mId , std::bind ( &test::func , *this ) );
}