Class 在 lambda 中更改时不会全局修改成员 - C++
Class member is not modified globally when changed in lamba - c++
我用 C++ 编写的一些代码有问题。我创建了两个 classes MyClass
和 Server
。 MyClass
具有类型为 std::vector<std::string>
的名为列表的成员。 Server
class 有一个名为 RegisterRoute
的方法,用于将回调方法绑定到字符串(API 路由)并将绑定添加到 std::map
名为 routemap
的成员。服务端收到请求后,查找请求中的路径url,调用已经绑定的对应函数
我在主程序中实例化了 MyClass
和 Server
的实例,调用了 MyClass::MyObject
和 Server::MyServer
,我使用 [=28= 将回调 lambda 绑定到路由].在这个 lambda 中,我通过引用将 MyObject
传递给 lambda,然后我调用了一个将项目添加到 std::vector<>
的方法。问题是在 lambda 的范围之外,对象似乎没有被修改。因此,每次我调用路由时,列表似乎都不受之前 lambda 调用的影响。 lambda的形式如下图
[&MyObject](std::string item){
MyObject.addItem(item);
MyObject.showList();
}
如果我在 MyObject.addItem()
之后调用 lambda 中的 MyObject.showlist()
方法,列表将显示为已修改。但是,当我点击一条路线来显示列表(调用 MyObject.showlist()
)时,它会显示调用最后一个 addItem
路线之前的对象时创建的原始列表。此外,如果我在 lambda 外部调用 addItem 方法,则会修改列表。
int main(){
MyClass MyObject("new list"); //Constructor to take string and add it to std::vector<std::string> list
Server MyServer(4564); //Constructor to create server and bind port to socket
MyServer.RegisterRoute("/additem",[&MyObject](std::string item){
MyObject.addItem(item);
MyObject.show();
return "added";
});
MyObject.addItem("Dummy Item"); //This item is seen in the list when show list calls
MyServer.StartServer();
return 0;
}
我认为通过引用传递对象将允许在 lambda 中所做的修改影响原始对象,有人可以告诉我我可能遗漏了什么吗?
编辑...
我意识到我遗漏了部分调用链。
RegisterRoute 用于将定义的回调添加到路由映射。
void MyServer::RegisterRoute(std::string route,std::function<std::string(std::string)>routehandle){
this->routemap.emplace(std::make_pair(route,routehandle));
};
MyServer Class 调用 Listen 方法,该方法接受在收到传入连接时执行的回调。
void MyServer::StartServer(){
Listen(httphandle);
};
httphandle 是 MyServer 的成员函数,它定义了如何处理请求。
void MyServer::httphandle(char* buffer, int socket){
char* requestbuffer = buffer;
std::stringstream datastream,headerstream;
auto requestline = strtok(requestbuffer,"\n");
auto header = strtok(nullptr,"\n");
headerstream << header << "\n";
while((header != nullptr) && (strlen(header)>1)){
header = strtok(nullptr,"\n");
headerstream << header <<"\n";
}
auto data = strtok(nullptr,"\n");
char* reqline[3];
reqline[0] = strtok (requestline, " \t\n");
if(routemap.find(reqline[1]) != routemap.end()){
auto reponsestring = routemap[reqline[1]](data);
write(socket, "HTTP/1.0 200 OK\n\n", 17);
write(socket, reponsestring.c_str(), strlen(reponsestring.c_str()));
}
else
write(socket, "HTTP/1.0 404 Not Found\n\n{\"error\":\"Not Found\"}\n", strlen("HTTP/1.0 404 Not Found\n\n{\"error\":\"Not Found\"}\n")); //FILE NOT FOUND
}
正是在这个回调中,存储的 lambda 将由路由映射查找执行。
我可以确认 lambda 正在调用,因为每次我点击路线时我都会调用 showlist 方法,它显示项目已添加。当我再次调用 addItem 路由时,列表不显示之前添加的。
*对于错误的问题格式,我深表歉意,这是我的第一个问题,我的代码很重,所以我试图简化问题。
好的,在考虑了这个过程之后我意识到问题不在于 lambda,而实际上在于套接字代码。我正在使用 fork()
来处理 MyServer::Listen()
函数中的新连接。这将创建一个新的子进程并将父内存复制到一个新的内存段,但由于内存未共享,父进程不会更新。因此,每次调用都会产生一个具有原始父内存的新子进程。我删除了对 fork 的调用,对象确实在每次调用后更新并反映在后续调用中。
最近介绍 lambda 函数时,我一直在思考它们。我将努力寻找解决此 child/parent 问题的方法。
我用 C++ 编写的一些代码有问题。我创建了两个 classes MyClass
和 Server
。 MyClass
具有类型为 std::vector<std::string>
的名为列表的成员。 Server
class 有一个名为 RegisterRoute
的方法,用于将回调方法绑定到字符串(API 路由)并将绑定添加到 std::map
名为 routemap
的成员。服务端收到请求后,查找请求中的路径url,调用已经绑定的对应函数
我在主程序中实例化了 MyClass
和 Server
的实例,调用了 MyClass::MyObject
和 Server::MyServer
,我使用 [=28= 将回调 lambda 绑定到路由].在这个 lambda 中,我通过引用将 MyObject
传递给 lambda,然后我调用了一个将项目添加到 std::vector<>
的方法。问题是在 lambda 的范围之外,对象似乎没有被修改。因此,每次我调用路由时,列表似乎都不受之前 lambda 调用的影响。 lambda的形式如下图
[&MyObject](std::string item){
MyObject.addItem(item);
MyObject.showList();
}
如果我在 MyObject.addItem()
之后调用 lambda 中的 MyObject.showlist()
方法,列表将显示为已修改。但是,当我点击一条路线来显示列表(调用 MyObject.showlist()
)时,它会显示调用最后一个 addItem
路线之前的对象时创建的原始列表。此外,如果我在 lambda 外部调用 addItem 方法,则会修改列表。
int main(){
MyClass MyObject("new list"); //Constructor to take string and add it to std::vector<std::string> list
Server MyServer(4564); //Constructor to create server and bind port to socket
MyServer.RegisterRoute("/additem",[&MyObject](std::string item){
MyObject.addItem(item);
MyObject.show();
return "added";
});
MyObject.addItem("Dummy Item"); //This item is seen in the list when show list calls
MyServer.StartServer();
return 0;
}
我认为通过引用传递对象将允许在 lambda 中所做的修改影响原始对象,有人可以告诉我我可能遗漏了什么吗?
编辑... 我意识到我遗漏了部分调用链。
RegisterRoute 用于将定义的回调添加到路由映射。
void MyServer::RegisterRoute(std::string route,std::function<std::string(std::string)>routehandle){
this->routemap.emplace(std::make_pair(route,routehandle));
};
MyServer Class 调用 Listen 方法,该方法接受在收到传入连接时执行的回调。
void MyServer::StartServer(){
Listen(httphandle);
};
httphandle 是 MyServer 的成员函数,它定义了如何处理请求。
void MyServer::httphandle(char* buffer, int socket){
char* requestbuffer = buffer;
std::stringstream datastream,headerstream;
auto requestline = strtok(requestbuffer,"\n");
auto header = strtok(nullptr,"\n");
headerstream << header << "\n";
while((header != nullptr) && (strlen(header)>1)){
header = strtok(nullptr,"\n");
headerstream << header <<"\n";
}
auto data = strtok(nullptr,"\n");
char* reqline[3];
reqline[0] = strtok (requestline, " \t\n");
if(routemap.find(reqline[1]) != routemap.end()){
auto reponsestring = routemap[reqline[1]](data);
write(socket, "HTTP/1.0 200 OK\n\n", 17);
write(socket, reponsestring.c_str(), strlen(reponsestring.c_str()));
}
else
write(socket, "HTTP/1.0 404 Not Found\n\n{\"error\":\"Not Found\"}\n", strlen("HTTP/1.0 404 Not Found\n\n{\"error\":\"Not Found\"}\n")); //FILE NOT FOUND
}
正是在这个回调中,存储的 lambda 将由路由映射查找执行。
我可以确认 lambda 正在调用,因为每次我点击路线时我都会调用 showlist 方法,它显示项目已添加。当我再次调用 addItem 路由时,列表不显示之前添加的。
*对于错误的问题格式,我深表歉意,这是我的第一个问题,我的代码很重,所以我试图简化问题。
好的,在考虑了这个过程之后我意识到问题不在于 lambda,而实际上在于套接字代码。我正在使用 fork()
来处理 MyServer::Listen()
函数中的新连接。这将创建一个新的子进程并将父内存复制到一个新的内存段,但由于内存未共享,父进程不会更新。因此,每次调用都会产生一个具有原始父内存的新子进程。我删除了对 fork 的调用,对象确实在每次调用后更新并反映在后续调用中。
最近介绍 lambda 函数时,我一直在思考它们。我将努力寻找解决此 child/parent 问题的方法。