作为一名经验丰富的C++程序员试图习惯于.NET,微软的WeakReference"Target"属性中有一个实现细节,这让我很烦恼......
public class WeakReference : ISerializable
{
internal IntPtr m_handle;
internal bool m_IsLongReference;
...
public virtual object Target
{
[SecuritySafeCritical]
get
{
IntPtr handle = this.m_handle;
if (IntPtr.Zero == handle)
{
return null;
}
object result = GCHandle.InternalGet(handle);
if (!(this.m_handle == IntPtr.Zero))
{
return result;
}
return null;
}
[SecuritySafeCritical]
set
{
IntPtr handle = this.m_handle;
if (handle == IntPtr.Zero)
{
throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_HandleIsNotInitialized"));
}
object oldValue = GCHandle.InternalGet(handle);
handle = this.m_handle;
if (handle == IntPtr.Zero)
{
throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_HandleIsNotInitialized")); …Run Code Online (Sandbox Code Playgroud) 所以我知道这里的基础知识 - 当一个对象不再可以被根访问时(即来自堆栈帧中的局部变量或静态引用的强引用),该对象有资格进行垃圾回收.
我的问题是这个潜在的优化,即使从局部变量引用一个对象,它也可能在函数中不再引用该变量的任何点进行垃圾收集.首先 - 似乎现有的C#实现不会这样做 - 2.0和4.0似乎都会保持本地引用"直播",直到堆栈帧被销毁.但是 - 如果在CLR的更高版本中优化垃圾收集时,我还想编写仍然健壮的代码.
所以 - 不用多说了,这里有一些代码说明:
class Foo
{
...
}
class Program
{
public static void fxn1(int blah)
{
...
}
public static void fxn2(Foo foo)
{
...
}
public static int ToInt(Foo foo)
{
...
}
public static void Main()
{
...
Foo foo = new Foo();
fxn2(foo); // I THINK foo may not be GC'ed until fxn2 returns...
// I THINK foo may be GC'ed here, even though CLR2.0 and …Run Code Online (Sandbox Code Playgroud) 这可能有点特定于实现,但有些似乎是根本性的.
我确定我必须在标准库中遗漏一些东西.
问题是这样的:
我想实现一个std::unique_ptr删除器free()
[因为价值是通过malloc()] 分配的
当然,有很多选项可以做到这一点,但(至少在g ++ 4.8.4 for x86-64中)它们似乎有不同的内存使用含义.
例如:方法1:
std::unique_ptr<char, std::function<void(void*)>> ptr_a(malloc(10), free);
Run Code Online (Sandbox Code Playgroud)
但是,
sizeof(ptr_a)== 40个字节(对于void*为8,对于std :: function <>为32)
方法2:
std::unique_ptr<void, void (*)(void*)> ptr_b(malloc(10), free);
Run Code Online (Sandbox Code Playgroud)
好一点,因为
sizeof(ptr_b)== 16个字节(8个用于void*,8个用于裸函数指针])
方法3:
template <void (*T)(void*)>
class Caller {
public:
void operator()(void* arg) {
return T(arg);
}
};
std::unique_ptr<void, Caller<free>> ptr_c(malloc(10));`
Run Code Online (Sandbox Code Playgroud)
在这一点上,sizeof(ptr_c)== 8个字节(最小可能) - 但我必须引入一个非常纯粹的样板(并且如图所示,容易模板化)的类.
这看起来像是一个简单的模式 - STL中是否有一些元素能够Caller<>完成上述操作?
当然,默认情况下,当在一个普通类型上调用delete时,g ++确实看起来像free() - 但这似乎远不是标准所保证的(如果没有别的,可以从默认的分配/释放函数重新定义new/delete,并且然后default_delete将调用替换删除).
此外,在其他情况下,在纯C库中分配的某些对象的发布将通过简单的函数调用而不是删除器来实现.在类中包含这样的分配/释放函数似乎有点乏味,以便让std :: unique_ptr正确有效地调用它们 - 这让我觉得我缺少了一些东西(现代C++规范的其余部分)似乎非常深思熟虑).