我正在研究一个项目,我遇到了循环依赖的问题。我最初希望Device类使用Simulation类向另一个发送消息,为此,Simulation类必须具有所有已创建设备的记录列表,以便向它们发送中继消息。
无论如何,我尝试了另一种使用中间人修复循环依赖问题的方法 - void RelayMessage()。它工作正常,直到我取消注释线程声明。我不知道它为什么会给我错误:
严重级代码说明项目文件行抑制状态错误 (有效)E1776功能“Device :: Device(const Device&)”(声明 隐含地)不能被引用 - 它被删除了 function testingProject c:\ Users \ osfer \ Documents \ Visual Studio 2017 \ Projects \ testingProject \ testingProject \ main.cpp 37
以下是代码:
#include <vector>
#include <string>
#include <thread>
static void RelayMessage(std::string message);
class Device {
public:
std::string incomingMessage = "";
std::string composedMessage;
//std::thread inputStream; // uncommenting this creates an error in class Simulation @ line 36
void relayMessage() {
RelayMessage(composedMessage);
}
void InputStream() {
while (true) {
if (incomingMessage != "")
printf("Message recieved!\n");
incomingMessage = "";
}
}
};
class Simulation {
public:
// record devices in simluation
static std::vector<Device> devicesInSim;
Simulation() {
// create 2 devices
devicesInSim.push_back(Device());
devicesInSim.push_back(Device());
}
};
static void RelayMessage(std::string message) {
// relays message to all devices
for (Device device : Simulation::devicesInSim) // error
device.incomingMessage = message;
}
int main() {
return 0;
}
答案 0 :(得分:3)
您正在尝试复制for
循环中的对象。 thread
不可复制。您应该使用引用迭代:
static void RelayMessage(std::string message) {
// relays message to all devices
for (auto& device : Simulation::devicesInSim)
device.incomingMessage = message;
}
(您也可以使用Device&
代替auto&
,但此处auto
非常明确。)
这可能就是你想到的。如果没有引用,您将更改incomingMessage
对象的副本而不是向量中包含的实际对象。使用基于范围的for
循环时,您需要记住,这会迭代容器中元素的副本:
for (auto i : container)
要迭代实际对象,请使用:
for (auto& i : container)
要获得对元素的只读访问权限,请使用:
for (const auto& i : container)
答案 1 :(得分:1)
正如评论和其他答案中所提到的,std::thread
没有复制构造函数,因此您需要通过引用传递它们。
另一个例子是处理文件时,即fstream
。由于没有复制构造函数,因此无法将fstream
个对象传递给函数。基本上发生的事情是,当您将对象传递给函数时,会创建一个仅对函数本地的副本(称为pass by value)。
由于thread
,fstream
等没有复制构造函数,因此在函数调用期间无法复制。因此,您必须使用&
和数据类型通过引用传递。
修改强> 这不是解决问题的方法,而是对它的一些见解,以便您知道下次发生的原因。