C++“智能指针”模板,自动转换为裸指针,但无法显式删除

2024-05-05

我正在一个非常大的遗留 C++ 代码库中工作,该代码库将保持匿名。作为遗留代码库,它在各处传递原始指针。但我们正在逐渐尝试使其现代化,因此也有一些智能指针模板。这些智能指针(与 Boost 的scoped_ptr 不同)具有到原始指针的隐式转换,因此您可以将其中之一传递到采用原始指针的例程中,而无需编写.get()。这样做的一个很大的缺点是,您也可能会不小心在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
}

标准说

操作数应具有指针类型,或具有到指针类型的单个转换函数(12.3.2)的类类型。如果操作数是类类型,则通过调用上述转换函数将操作数转换为指针类型,并在本节的其余部分中使用转换后的操作数代替原始操作数。

您可以通过声明转换函数的 const 版本来 (ab) 使用缺少重载解析的情况。在一个合格的编译器上,这足以使它不再工作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 /* ... */ }

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

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; }
};

但请注意,只有不符合标准的编译器才需要这些解决方法。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++“智能指针”模板,自动转换为裸指针,但无法显式删除 的相关文章

  • 为什么我应该使用内联代码? [复制]

    这个问题在这里已经有答案了 我是一名 C C 开发人员 这里有几个始终困扰我的问题 常规 代码和内联代码之间有很大区别吗 主要区别是什么 内联代码只是宏的一种 形式 吗 选择内联代码时必须进行什么样的权衡 Thanks 表现 正如之前的答案
  • 将 ARGB 拆分为字节值

    我有一个 ARGB 值存储为 int 类型 它是通过调用 ToArgb 来存储的 我现在想要来自 int 值的各个颜色通道的字节值 例如 int mycolor 16744448 byte r g b a GetBytesFromColor
  • C语言实现延时函数

    我想使用空循环实现延迟函数 但是完成一次循环所需的时间取决于编译器和机器 我希望我的程序自行确定时间并将程序延迟指定的时间 谁能给我任何想法如何做到这一点 注意 有一个名为delay 的函数可以将系统暂停指定的毫秒 是否可以在不使用此功能的
  • 更改图像颜色与透明背景

    我需要使用 c System Drawings 将透明背景上带有绿色圆圈的图像加载到位图图像中 这是最简单的部分 但是 我需要在将其添加到更大的图像之前更改圆圈的颜色 而不影响周围的透明度 就我而言 我需要将圆圈颜色更改为黄色并将其添加为太
  • C++:字符串流有什么好处?

    谁能告诉我一些在 C 中使用字符串流的实际例子 即使用流插入和流提取运算符输入和输出到字符串流 您可以使用字符串流来转换任何实现operator lt lt 到一个字符串 include
  • 值类型如何实现引用类型

    我遇到了一个值类型正在实现 ref 的场景 类型 只是想知道这怎么可能 幕后发生了什么 结构体是值类型 接口是引用 类型但结构可以实现接口而不会出现任何错误 有什么想法吗 提前致谢 实际上 它同时以两种不同的方式进行 首先 任何值类型都可以
  • C++ 并行任务的开销

    我有以下简单的功能 include
  • 我如何知道向量的实际最大大小? (不使用 std::vector::max_size)

    在在线课程中 我正在学习向量 在其中一个例子中 他们解释说 std vector max size 应该给我向量可以达到的最大大小 我决定测试一下 include
  • 编译器消息“警告:格式‘%s’需要类型‘char *’,但参数 2 具有类型‘char (*)’”

    我正在尝试运行一个简单的 C 程序 但收到此错误 警告 格式 s 需要类型 char 但参数 2 的类型为 char 20 我在跑步Mac OS X v10 8 https en wikipedia org wiki OS X Mounta
  • 是否自初始化 'A a = a;'允许吗?

    此代码在运行时在复制构造函数中失败 但编译器 MSVS2008 没有发出警告 您能解释一下 最好引用标准 这段代码是否非法或什么 我理解 A a a 永远不应该写在第一位 但我正在寻找理论背景 class A public A p new
  • 使用左连接获得不适当的输出

    我正在尝试获取变体列表 并且对于每个变体都获取所有subvariants list无论子变体属于何处 特别的Test say 100 这是示例数据 Id TestId SourceSubVariantId TargetSubVariantI
  • 使用信号和槽更新指针

    我对 Qt 很陌生 请帮我解决这个问题 我正在使用线程在后台执行密集操作 同时我想更新 UI 所以我使用 SIGNALS 和 SLOTS 为了更新 UI 我发出一个信号并更新 UI 让我们考虑下面的示例代码 struct sample QS
  • “DeploymentItem”属性是什么意思?

    假设我们有一个简短的程序 namespace ConsoleTryIt static class Program static void Main string args var sum Add 1 2 private static int
  • C中使用JNI从对象获取对象

    public class Student private People people private Result result private int amount 这是 Java 中类的示例 在C中 我试图获取 学生 中的 人 但失败了
  • 调用泛型类的方法

    这是上下文 我尝试编写一个映射器来动态地将域模型对象转换为 ViewModel 对象 我遇到的问题是 当我尝试通过反射调用泛型类的方法时 出现此错误 System InvalidOperationException 无法对 Contains
  • 如何从 C# 中的 Web Api 方法正确获取字节数组?

    我有以下控制器方法 HttpPost Route SomeRoute public byte MyMethod FromBody string ID byte mybytearray db getmybytearray ID working
  • 小数精度

    我使用小数类型进行高精度计算 货币 但我今天遇到了这个简单的划分 1 1 37 这应该再次得到 37 http www wolframalpha com input i 1 2F 281 2F37 29 http www wolframal
  • Selenium - 模式对话框存在 - 如何接受信息?

    我有以下问题 在页面上提交一些日期后 我有一个如图所示的模式对话框 我想单击 ENTER 来浏览该模式 但它不起作用 我有以下代码 driver FindElement By CssSelector input submit Click A
  • 如何使用实体框架设置连接字符串

    我将 EF6 与 MySQL 结合使用 并有一个用于多个数据库的模型 我希望能够在我的表单中设置连接设置 如何以编程方式设置模型的连接字符串 你应该使用EntityConnectionFactory这就是您所需要的 public strin
  • 从其对象获取结构体字段的名称和类型

    例如 我有一个类似这样的结构 struct Test int i float f char ch 10 我有一个该结构的对象 例如 Test obj 现在 我想以编程方式获取字段名称和类型obj 是否可以 顺便说一句 这是 C 你正在要求C

随机推荐

  • 在 macOS 上运行 Comma IDE 时找不到匹配的虚拟机

    我安装了 Comma IDEthis https commaide com download链接 但当我尝试通过双击应用程序文件夹中 Finder 中的应用程序图标来运行它时 出现错误 未找到匹配的 VM 需要 Java 1 8 或更高版本
  • jQuery 无法从本地主机检索数据

    我有一个非常简单的 jQuery 来检索我最新的推文 getJSON http twitter com statuses user timeline username json count 1 function data tweet tex
  • 更改在 docker 中运行的 selenium 节点的日志级别

    我们的团队正在使用 docker 部署 selenium 网格 默认日志级别似乎设置为 INFO 我想将其设置为更高的值 严重 或完全关闭它们 我已经进行了三次尝试 但到目前为止 没有效果 方法一 从 selenium 客户端 我尝试在 D
  • Foldmethod=同时标记和语法?

    同一文件是否可以根据标记和语法使用折叠 Since foldmethod一次只能设置为一个 我认为您真正可以做到这一点的唯一方法是使用 set foldmethod expr并与foldexpr 即使如此 我也不确定它是否能够完全按照您的要
  • 如何将 SQL 参数中的字符串数组传递给 SQL 中的 IN 子句

    我正在以复杂的方式做一个逻辑 我只需要在存储过程中执行此查询 select Sizes SUM Quantity from tbl SizeBreakup where Brand brand and Combo in 1 2 我必须在 C
  • for 循环语法,其中包含 if 语句

    使用 if 语句编写 for 循环的普遍共识是什么 for int i 0 i lt hi i if some invalid condition continue if another invalid condition continue
  • 我无法在 PyCharm 下运行 Django Python pytest

    pytest portal test session starts platform darwin Python 3 6 0 pytest 3 0 6 py 1 4 32 pluggy 0 4 0 Django settings confi
  • 如果服务器在使用 dblink 时未请求密码,则非超级用户无法连接

    我想在我的应用程序中进行一些跨数据库引用 简而言之 我有两个数据库 分别称为meta 和op 我想从元到 op 数据库中的表进行一些选择查询 如下所示 但出现以下错误 我尝试了有密码和无密码 顺便一提caixa用户是非超级用户 我的目标服务
  • 值类型不完整的映射

    我收到以下错误 class Test std map
  • 为什么 Pearson 相关输出为 NaN?

    我正在尝试获取 R 中变量之间的皮尔逊相关系数 这是变量的散点图 ggplot results summary aes x D in y D ex geom point col ifelse results summary FDR lt 0
  • socket.error:[Errno 10054]现有连接被远程主机强制关闭(python2.7)

    我的套接字有问题 它运行良好 但是当我关闭客户端 关闭客户端窗口时 服务器丢失了连接 服务器需要保持打开状态并等待其他连接 while True rlist wlist xlist select select server socket o
  • 迭代亚马逊S3上文件夹中的对象

    我们有一个应用程序 用户可以创建自己的网页并托管它们 我们使用 S3 来存储静态页面 在这里 由于我们每个用户有 100 个存储桶的限制 我们决定为每个用户使用文件夹桶内的用户 现在 如果用户想在他的域上托管他的网站 我们会向他询问域名 当
  • 如果我在 XML 布局中声明一个片段,如何将它传递为 Bundle?

    我有一个活动已替换为片段 该活动采用了一个 Intent 其中包含一些有关该活动应该显示哪些数据的额外信息 现在 我的 Activity 只是执行相同工作的 Fragment 的包装器 如果我使用标记在 XML 中声明该片段 如何将该捆绑包
  • Pipx 构建包失败

    当我运行命令 pipx install eth brownie 时 我收到以下错误消息 fatal error from pip prevented installation Full pip output in file Users ge
  • 具有基类的唯一 ptr 的类的复制构造函数[重复]

    这个问题在这里已经有答案了 当一个类具有基类的 unique ptr 时 实现复制构造函数的好方法是什么 让我尝试用一 个例子来解释它 struct Base virtual void doSth 0 to make the class a
  • 微软编码标准文档

    Microsoft 是否有可供下载的编码标准文档 我想使用他们的标准 主要针对 C 如果您使用 C 则可以通过运行以下命令在编码时了解 Microsoft 的首选风格StyleCop http code msdn microsoft com
  • Java:如何将ArrayList作为对象的实例变量?

    我正在开展一个班级项目 用 Java 构建一个小型 Connect4 游戏 我目前的想法是拥有一类 Columns 它具有一些整数 索引 最大长度 isFull 作为实例变量 以及一个 ArrayList 来接收上面的整数和每个玩家的表现
  • Async/Await 无法按预期使用 Promise.all 和 .map 函数

    我有很多async我正在使用的功能 但遇到了一个奇怪的问题 我的代码正在运行 如下所示 async mainAsyncFunc metadata let files metadata map data gt this anotherAsyn
  • 计算标签云中标签字体大小的公式是什么?

    我有一个标签云 我需要知道如何更改最常用标签的字体大小 我需要设置最小字体大小和最大字体大小 您可以使用线性或对数评估与某个标签相对于最大标签关联的项目数量 将其乘以最小和最大字体大小之间的差值 然后将其添加到最小字体大小 例如 伪代码中的
  • C++“智能指针”模板,自动转换为裸指针,但无法显式删除

    我正在一个非常大的遗留 C 代码库中工作 该代码库将保持匿名 作为遗留代码库 它在各处传递原始指针 但我们正在逐渐尝试使其现代化 因此也有一些智能指针模板 这些智能指针 与 Boost 的scoped ptr 不同 具有到原始指针的隐式转换