访问智能指针时的自定义操作
Custom operation when accessing a smart pointer
在我们的项目中,我们为一些类使用了一种特殊类型的指针,在访问指针时执行一些自定义代码(在我们的例子中是为了修改某些类的内存管理)。代码看起来像这样:
#include <iostream>
#include <memory>
void do_something(int i) {
std::cout << "+++ function(" << i << ") +++" << std::endl;
}
class C {
public:
int method() {
std::cout << "+++ C::method() +++" << std::endl;
return 42;
}
};
template <class T>
class ptr : public std::unique_ptr<T> {
public:
class proxy {
public:
proxy(T* t) : m_t(t) { std::cout << ">>> Begin access >>>" << std::endl; }
~proxy() { std::cout << "<<< End access <<<" << std::endl; }
T* operator->() { return m_t; }
private:
T* m_t;
};
public:
ptr(T* p) : std::unique_ptr<T>(p) {}
proxy operator->() { return proxy(std::unique_ptr<T>::get()); }
};
int main() {
ptr<C> pc(new C);
pc->method();
do_something(pc->method()); // <-- problem!
return 0;
}
因此,当使用指针访问底层对象时,将返回一个临时代理对象,该对象通过在其构造函数和析构函数中执行代码来修改指针访问行为(我认为在行末)。例如,当像上面的示例代码一样将对指针的访问与函数调用相结合时,就会出现问题。程序产生以下输出:
>>> Begin access >>>
+++ C::method() +++
<<< End access <<<
>>> Begin access >>>
+++ C::method() +++
+++ function(42) +++
<<< End access <<<
可以看到,临时代理对象只有在调用function()
之后才被销毁。然而,这并不是我们想要的行为(在我们的例子中,它会扰乱内存管理)。在这种情况下,一种解决方法是将被访问方法的结果保存在一个临时值中,并将两个调用分开:
int result = pc->method();
do_something(result);
这会将代理对象的生存期限制为预期的实际访问。当然,这有点容易出错,因为编译器允许合并两个函数调用,所以您很容易忘记它。
问题:你能想到一种方法来限制代理对象的生命周期到实际访问(我认为这可能是不可能的),或者让编译器通知你错误地使用了一个错误或警告构造吗?
首先,我真的不会从unique_ptr
继承,而是与组成
如果你坚持你的客户端函数接受一个裸的T *
,那么任何合适的转换到这个类型必须发生在调用者的范围内,所以你永远不会产生你的副作用"就像指针被解引用一样"。
在这种情况下,我个人会尝试采用一种方法,通过这种方法,客户端接受您的智能指针:
void do_something(WorkPointer<Foo> & p);
要实现WorkPointer
,替换解引用操作符:
template <typename T> struct WorkPointer
{
proxy operator->() { return proxy(m_p.get()); }
private:
std::unique_ptr<T> m_p;
// ...
};
如果您想在解引用之后执行操作,则仍然需要代理。如果不需要,您可以直接将额外的工作放入解引用操作符中。
我认为这个问题并没有很好地定义,并且您可能永远不应该依赖于"访问后"代码调用的确定时间。想象一下下面的用法:
void some_function(WorkPointer<Foo> & p)
{
Foo & f = *p; // #1
something_else(f);
}
现在"before"和"after"代码将在时间线#1结束时运行。由于这完全是指针的典型用法,因此您必须预料到这一点。然而,something_else(*p)
是一种可选调用,它将导致在something_else
函数调用结束后调用"after"代码。
我不认为你可以通过任何简单的"插入式替换"的方式来解决这个问题,所以你可能应该重新设计你的代码,这样它就不需要这种双管齐下的控制了。
- 编译 GPU 的张量流示例自定义操作
- (Wix 安装程序)如何包含自定义操作依赖项
- 带有资源句柄的TensorFlow自定义C++操作
- CPP DLL 自定义操作代码在安装过程中未执行
- 使用 c++ 时如何加载自定义操作库?
- 如何根据自定义操作中的属性集安装功能
- 如何在自定义操作DLL(MSI / Wix)中获取"INSTALLED"属性?
- 为什么 Tensorflow 找不到我的自定义操作的 GPU 内核?
- 如何在 cocos2d-x 中创建自定义操作
- 使用 libfm Linux 的 C 中的自定义操作或命令?
- MSI安装被自定义操作DLL中断
- 关于Tensorflow和PyTorch中的自定义操作
- 在 TensorFlow 中加载自定义操作时出现未定义的符号错误
- 如何在单个自定义操作项目中创建多个C 自定义操作
- 可视化如何从C++自定义操作获取 MSI 'UILevel'属性
- Windows安装程序,成功执行后自定义操作出现错误2896
- C++自定义操作DLL的路径
- Windows安装程序,在C++中访问自定义操作中的自定义属性
- 使用Visual Studio 2010 Ultimate制作自定义操作dll
- 如何创建自定义操作以更改文件权限