返回 C++ 对象时的复制和销毁

2024-06-26

我有一段相当简单的测试代码:

#include <stdio.h>

class PG
{
public:

PG(){
    m_ptr = new int;
    printf("Created PG %i\n", (int)m_ptr);
} 

~PG(){
    printf("Deleted PG %i\n", (int)m_ptr);
    delete (m_ptr);
}

PG& operator =(const PG& src)
{
    printf("Copied PG %i %i\n", (int)m_ptr, (int)src.m_ptr);
    return(*this);
}

private:
    int * m_ptr;
};

PG CreatePG()
{
    PG ret;
    return ret;
}

int main(int argc, char* argv[])
{
    PG test;
    test = CreatePG();
    printf("Ending\n");
    return 0;
}

如果我使用 GCC、VS2008 或 VS2012 进行全面优化编译并运行它,我会得到我所期望的结果:
创建 PG 7837600- 创建测试
创建 PG 7689464-创建 ret
复制 PG 7837600 768946-复制 ret 进行测试
已删除 PG 7689464-删除ret
Ending
已删除 PG 7837600-删除测试

然而,当我在没有优化的 VS2008 或 VS2012 上编译时,我得到这个:
创建PG 3888456- 创建测试
创建PG 4036144-创建 ret
已删除 PG 4036144-删除了 ret。等等,我们还没有复制它!
复制PG 3888456 4036144-我们现在正在尝试复制已删除的数据
已删除 PG 4036144-这已经被删除了。应用程序崩溃

我不敢相信这是 VS 中的一个从未修复过的错误,但我也看不出我做错了什么。在我的应用程序中,我有一个实例,在编译针对速度进行优化的更复杂的类时也会发生这种行为。我知道使用以下方法会更有效:

 PG test = CreatePG();

但我仍然遇到类似的问题,尽管在这种情况下显然使用了复制省略:
创建PG 11228488
已删除 PG 11228488
Ending
已删除 PG 11228488
我仍然得到双重删除。

如果有人能对此有所启发,我将非常感激。


这是因为您的代码违反了三法则 http://en.wikipedia.org/wiki/Rule_of_three_%28C++_programming%29:由于您没有复制构造函数,因此在幕后发生了一些重要的事情,而您看不到打印输出。

当您没有复制构造函数时,C++ 很乐意为您定义一个复制构造函数。这通常是您想要的确切构造函数,但在一种情况除外:当您的类显式管理资源时。在这种情况下,当同一指针可以被多次删除时,逐字节复制内容会创建错误别名。当您打开优化时,编译器会跳过复制构造函数的调用(返回值优化)。然而,在关闭优化的情况下,复制构造函数被调用,然后m_ptr被删除,留下指向已删除内存的实际指针。

以下是解决此问题的方法:

PG& operator =(const PG& src) {
    *m_ptr = *(other->m_ptr);
    printf("Assigned PG %x %x\n", (void*)m_ptr, (void*)src.m_ptr);
    return(*this);
}
PG(const PG& other) {
    m_ptr = new int;
    *m_ptr = *(other->m_ptr);
    printf("Copied PG %x\n", (void*)m_ptr);
}

注意:将指针转换为int没有定义;你应该将指针转换为void*,并打印%x格式说明符。

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

返回 C++ 对象时的复制和销毁 的相关文章

  • 以 ISO 8601 格式输出日期

    如何在 C 中获取以下格式的日期 2016 04 26T19 50 48Z include
  • OWIN AuthenticationOptions 在 mvc5 应用程序中运行时更新

    Hi 情况如下 我在 iis 7 上有一个带有 Identity 2 的 MVC 5 应用程序 该应用程序为多个网站提供服务 主机名是某些网站的关键 网站 另一个网站 等等 我决定在我的所有网站上使用谷歌外部登录 每个网站都应该是带有个人
  • 多态性中基类缺少虚拟析构函数 = 资源泄漏?

    我们知道 如果要多态地使用基类 则需要将基类的析构函数指定为 virtual 否则程序中可能会出现资源泄漏 因为只会调用基类析构函数 而不会调用派生对象析构函数 我们还知道构造函数 析构函数纯粹是初始化 未初始化构造 而operator n
  • 如何处理作为参数传递到方法中的 Lambda 表达式 - C# .NET 3.5

    我对 Lambda 表达式的了解有点不稳定 虽然我可以编写使用 Lambda 表达式 又名 LINQ 的代码 但我正在尝试编写自己的方法 该方法采用一些 Lambda 表达式类型的参数 背景 我正在尝试编写一个方法 该方法从任何其他对象类型
  • Linux C++ 调试器

    我正在寻找完美的 Linux C 调试器 我不期望成功 但搜索应该提供丰富的信息 我是一个非常有能力的 gdb 用户 但 STL 和 Boost 很容易压垮我的调试技能 并不是说我无法深入了解数据结构的内部结构 而是它需要很长时间 我通常会
  • 第三方引用的 dll 未被复制来构建

    我有一个第三方 net dll 被我的 dll 类库项目 A 引用和使用 我的控制台应用程序项目 B 引用项目 A 我的问题是第三方 dll 没有被复制到控制台应用程序项目 B 的构建中 这里有什么问题呢 我的 dll 类库中引用的第三方
  • UWP - 绑定枚举差异

    我遇到了一个非常有趣的问题 假设 UWP 应用中有以下 XAML 页面内容
  • Excel 2007 中的数值 - 底层 xml 文件中的表示与存储

    这个问题与 NET和OpenXml有关 我已经阅读了以下文章 它有很好的解释 但没有回答我的问题 Excel 2007 中数值的可视化与底层 xml 文件不一致 https stackoverflow com questions 58594
  • OpenMP 循环数组访问中的错误共享

    我想利用 OpenMP 来并行执行我的任务 我需要将数组的所有元素减去相同的数量并将结果写入另一个向量中 两个数组都是动态分配的malloc第一个填充了文件中的值 每个元素都有类型uint64 t pragma omp parallel f
  • 如何在 C++ 中初始化嵌套类的构造函数

    我在初始化嵌套类构造函数时遇到问题 这是我的代码 include
  • 嘲笑会员用户

    我目前正在开发一个 asp net mvc 2 应用程序 它使用默认的 SqlMembershipProvider 进行身份验证 我已经实现了一个控制器方法 通过调用读取当前用户的 ProviderUserKeyMembership Get
  • WPF MVVM后台打印数据绑定问题

    我正在使用 wpf mvvm 开发一个销售点应用程序 在交易生命周期的许多阶段 都会在后台打印收据 我已经使用其他示例在后台生成和打印收据 我正在后台打印一个 UserControl 一切看起来都很棒 然后 我为该控件创建了 ViewMod
  • 除法时的小数舍入误差 (C#)

    我基本上有四个数字 比如 100 200 300 400 我需要计算概率为 100 100 200 300 400 200 100 200 300 400 等等在 当我使用小数数据类型来存储这些概率时 由于舍入问题 它们不会达到 1 在不使
  • 链接错误:xxx 已在 *****.LIB 中定义:: 究竟出了什么问题?

    Problem 我正在尝试使用一个名为DCMTK http dicom offis de dcmtk它使用了一些其他外部库 zlib libtiff libpng libxml2 libiconv 我已经从同一网站下载了这些外部库 LIB
  • 如何在 Windows 8.1 上打开多个 Visual Studio 窗口? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我使用的是 Windows 7 我能够启动多个 Visual Studio 并同时工作 现在我有 Windows 8 1 操作系统 每当我
  • 为什么 ASP.Net MVC Range 属性采用类型?

    我只是想知道为什么范围验证属性可以采用类型和两个字符串作为参数 这是为了根据枚举或类似的东西验证字符串吗 另外 我想做的是找到一种简单的方法来验证必须出现在枚举中的 3 个字符的字符串 有什么建议吗 谢谢 亚历克斯 我确实发现你提到的 Ra
  • 没有类型的 IEnumerable 属性

    我正在尝试创建一个类似于来自 MSDN 的官方 DataGrid ItemsSource 的属性 public IEnumerable ItemsSource get set 这提供了对任何派生类中任何类型的支持 有了这个 我可以设置类似的
  • 每次运行 Visual Studio 时如何修复“项目已过期”消息

    我有一个包含 70 个项目的 Visual Studio 2005 解决方案文件 每次我按 F5 运行它时 它都会告诉我其中 4 个项目已过时 并询问我是否要重建它们 即使我刚刚完成了完整的构建 它也会这样做 我理解 原则上 其他项目之一必
  • 矩阵行列式算法 C++

    我是编程新手 我一直在寻找一种找到矩阵行列式的方法 我在网上找到了这段代码 但我很难理解这里的算法 我对递归的基础没有问题 但继续和主循环我很难理解 非常感谢任何可以向我解释该算法的人 int determ int a MAX MAX in
  • 更快的 WinSock sendto()

    我使用的是 Windows Server 2008 我的程序是用 C 编写的 我在 while true 循环中使用 WinSock2 和 sendto 来发送数据包 代码如下 while true if c snd gt max c sn

随机推荐