gpt4 book ai didi

C++ "smart pointer"自动转换为裸指针但不能显式删除的模板

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:03:09 24 4
gpt4 key购买 nike

我在一个非常大的遗留 C++ 代码库中工作,该代码库将保持匿名。作为遗留代码库,它到处传递原始指针。但我们正逐渐尝试使其现代化,因此也有一些智能指针模板。这些智能指针(与 Boost 的 scoped_ptr 不同)具有到原始指针的隐式转换,因此您可以将其中之一传递到采用原始指针的例程中,而无需编写 .get()。这样做的一个很大的缺点是您也可能不小心在 delete 语句中使用了一个,然后就会出现双重释放错误,这真的很难追踪。

有没有办法修改模板,使它仍然具有到原始指针的隐式转换,但如果在 delete 语句中使用会导致编译错误?像这样:

#include <my_scoped_ptr>

struct A {};
extern void f(A*);

struct B
{
scoped_ptr<A> a;

B();
~B();
};

B::B()
: a(new A)
{
f(a); // this should compile
}

B::~B()
{
delete a; // this should NOT compile
}

最佳答案

标准说

The operand shall have a pointer type, or a class type having a single conversion function (12.3.2) to a pointer type. If the operand has a class type, the operand is converted to a pointer type by calling the above-mentioned conversion function, and the converted operand is used in place of the original operand for the remainder of this section.

您可以 (ab)- 通过声明转换函数的 const 版本来使用重载决议的缺失。在符合标准的编译器上,足以使其不再与 delete 一起工作:

struct A {
operator int*() { return 0; }
operator int*() const { return 0; }
};

int main() {
A a;
int *p = a; // works
delete a; // doesn't work
}

结果如下

[js@HOST2 cpp]$ clang++ main1.cpp
main1.cpp:9:3: error: ambiguous conversion of delete expression of type 'A' to a pointer
delete a; // doesn't work
^ ~
main1.cpp:2:3: note: candidate function
operator int*() { return 0; }
^
main1.cpp:3:3: note: candidate function
operator int*() const { return 0; }
^
1 error generated.

在这方面不太符合要求的编译器(EDG/Comeau、GCC)上,您可以将转换函数设为模板。 delete 不需要特定 类型,所以这会起作用:

template<typename T>
operator T*() { return /* ... */ }

但是,这有一个缺点,即您的智能指针现在可以转换为任何 指针类型。虽然实际的转换仍然是类型检查,但这并不能排除预先转换的可能性,而是会在很久以后给出编译时错误。遗憾的是,SFINAE 似乎无法使用 C++03 中的转换函数 :) 另一种方法是从其他函数返回私有(private)嵌套类型指针

struct A {
operator int*() { return 0; }

private:
struct nested { };
operator nested*() { return 0; }
};

现在唯一的问题是转换为 void*,在这种情况下,两个转换函数同样可行。 @Luther 建议的解决方法是从另一个转换函数返回一个函数指针类型,它适用于 GCC 和 Comeau,并且摆脱了 void* 问题,同时没有其他问题通常的转换路径,与模板解决方案不同

struct A {
operator int*() { return 0; }

private:
typedef void fty();
operator fty*() { return 0; }
};

请注意,这些解决方法仅适用于不符合规范的编译器。

关于C++ "smart pointer"自动转换为裸指针但不能显式删除的模板,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3312031/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com