【发布时间】:2013-06-26 22:42:42
【问题描述】:
当然我想知道一些神奇的解决方法,但我愿意重组。
所以我有一个类DeviceDependent,具有以下构造函数
DeviceDependent(Device& device);
存储对设备的引用。设备可以更改状态,这将需要更改依赖于该设备的所有DeviceDependent 实例。 (你猜对了,这是我骑着 DirectX 野兽的微不足道的尝试)
为了处理这个问题,我有函数DeviceDependent::createDeviceResources()、DeviceDependent::onDeviceLost()。
我计划将每个DeviceDependentinstance 注册到DeviceDependent 构造函数中指定的设备。设备将保留所有已注册的DeviceDependent 实例中的std::vector<DeviceDependent*>。然后它将遍历该向量并在适当的时候调用上述函数。
这看起来很简单,但我特别喜欢它的是我可以在代码的其他地方添加std::vector<DeviceDependent (or child)> 并快速迭代它们。例如,我有一个类 Renderable,顾名思义,它代表一个可渲染对象,我需要至少每帧迭代一次,因此我不希望对象分散在整个内存中。
言归正传,问题来了:
当我创建实体对象时,我依赖于移动语义。这纯粹是出于本能,我没有考虑复制像这样的大型对象以将它们添加到 std::vector<DeviceDependent (or child)> 集合中。 (并且仍然厌恶这个想法)
然而,随着移动语义(我已经为那些不相信它的人测试过),对象的地址会发生变化。更重要的是它在调用默认构造函数后发生了变化。这意味着我在 DeviceDependant 的构造函数中调用 device.registerDeviceDependent(this) 的代码编译并运行良好,但设备会累积一个指针列表,一旦对象移动到向量中,这些指针就会失效。
我想知道是否有什么方法可以让我坚持这个计划并让它发挥作用。
我想到的事情:
使“真实”向量成为共享指针的集合,复制没有问题。该对象大概不会更改地址。我不喜欢这个计划,因为我担心把东西放在堆上会损害迭代性能。
在对象被移动后调用 register,这是我暂时要做的,但我不喜欢它,因为我觉得构造函数是执行此操作的合适位置。那里 不应存在不在某些设备清单上的
DeviceDependent实例。编写我自己的移动构造函数或移动赋值函数。这样我就可以从设备中删除旧地址并将其更改为新地址。我不想这样做,因为我不想随着课程的发展而不断更新它。
【问题讨论】:
-
DeviceDependent是一种设备吗?如果是这样,您应该只有Device,并且应该拥有多个Devices(取决于这个Device)。 -
"在调用默认构造函数后它会发生什么变化。" -- 这根本没有任何意义。一旦创建了一个对象,地址就是它的身份——它只能在你谈论不同的对象时改变。
-
我不会将此作为答案发布,因为我不确定这是您要的,但here's one way to do what I think you're asking
-
@AnotherTest 不,DeviceDependent 不是一种设备。设备通过 Microsoft::WRL::ComPtr 管理多个 COM 接口(包装一个包装器 :p)。 DeviceDependent 使用这些接口,但不应该每个都有一个,如果它是派生类就会发生这种情况。想象一下 ToolChest,车库里的所有工人都依赖工具来运作,但他们本身并不是 ToolChest 的一种。 (至少我是这么想的)
-
@TomKnapen 我希望这不会花你太长时间。是的,我认为这会起作用,因为
DeviceDependant::DeviceDependant(DeviceDependant && dep) : device_(nullptr) { dep.unregister_self(); std::swap(device_, dep.device_); register_self(); }这是正确的移动构造函数,这意味着移动语义将起作用并且设备中的指针将更新。如果您认为这可能是最好的选择,我只是不想在更改 DeviceDependent 时继续更新该功能。最后一件事,我不必为派生类定义移动构造函数,对吧?
标签: c++ c++11 directx move standard-library