动态分配对象数组

2024-05-04

我有一个包含动态分配数组的类,例如

class A
{
    int* myArray;
    A()
    {
        myArray = 0;
    }
    A(int size)
    {
        myArray = new int[size];
    }
    ~A()
    {
        // Note that as per MikeB's helpful style critique, no need to check against 0.
        delete [] myArray;
    }
}

但现在我想创建这些类的动态分配数组。这是我当前的代码:

A* arrayOfAs = new A[5];
for (int i = 0; i < 5; ++i)
{
    arrayOfAs[i] = A(3);
}

但这件事炸得很厉害。因为新A创建的对象(使用A(3)调用)被破坏时for循环迭代结束,这意味着内部myArray那个A实例获取delete []-ed.

所以我认为我的语法一定是非常错误的?我想有一些修复看起来有点矫枉过正,我希望避免这些修复:

  • 创建一个复制构造函数A.
  • Using vector<int> and vector<A>所以我不必担心这一切。
  • 而不是有arrayOfAs是一个数组A对象,让它是一个数组A*指针。

我认为这只是一些初学者的事情,当尝试动态分配具有内部动态分配的事物数组时,有一种语法实际上可以工作。

(另外,风格批评值得赞赏,因为我已经有一段时间没有使用 C++ 了。)

为未来的观众更新: 下面的所有答案都非常有帮助。 Martin 的被接受是因为示例代码和有用的“4 规则”,但我真的建议阅读它们。有些是对问题的简洁明了的陈述,有些正确地指出了错误的原因和方式vector这是一个很好的方法。


为了构建容器,您显然希望使用标准容器之一(例如 std::vector)。但这是当您的对象包含 RAW 指针时需要考虑的事情的完美示例。

如果你的对象有一个 RAW 指针,那么你需要记住 3 规则(现在是 C++11 中的 5 规则)。

  • 构造函数
  • 析构函数
  • 复制构造函数
  • 赋值运算符
  • 移动构造函数 (C++11)
  • 移动赋值 (C++11)

这是因为如果未定义,编译器将生成这些方法自己的版本(见下文)。在处理 RAW 指针时,编译器生成的版本并不总是有用。

复制构造函数是很难正确的(如果您想提供强大的异常保证,那么它就很重要)。赋值运算符可以根据复制构造函数来定义,因为您可以在内部使用复制和交换习惯用法。

有关包含指向整数数组的指针的类的绝对最小值的完整详细信息,请参阅下文。

知道正确使用它并不简单,您应该考虑使用 std::vector 而不是指向整数数组的指针。该向量易于使用(和扩展)并涵盖与异常相关的所有问题。将下面的类与下面 A 的定义进行比较。

class A
{ 
    std::vector<int>   mArray;
    public:
        A(){}
        A(size_t s) :mArray(s)  {}
};

看看你的问题:

A* arrayOfAs = new A[5];
for (int i = 0; i < 5; ++i)
{
    // As you surmised the problem is on this line.
    arrayOfAs[i] = A(3);

    // What is happening:
    // 1) A(3) Build your A object (fine)
    // 2) A::operator=(A const&) is called to assign the value
    //    onto the result of the array access. Because you did
    //    not define this operator the compiler generated one is
    //    used.
}

编译器生成的赋值运算符几乎适用于所有情况,但当使用 RAW 指针时,您需要注意。在你的情况下,它导致了一个问题,因为浅拷贝问题。您最终得到了两个包含指向同一块内存的指针的对象。当 A(3) 在循环结束时超出范围时,它会对其指针调用 delete[]。因此,另一个对象(在数组中)现在包含一个指向已返回到系统的内存的指针。

编译器生成的复制构造函数;使用该成员复制构造函数复制每个成员变量。对于指针,这仅意味着指针值从源对象复制到目标对象(因此是浅复制)。

编译器生成的赋值运算符;使用成员赋值运算符复制每个成员变量。对于指针,这仅意味着指针值从源对象复制到目标对象(因此是浅复制)。

因此,包含指针的类的最小值:

class A
{
    size_t     mSize;
    int*       mArray;
    public:
         // Simple constructor/destructor are obvious.
         A(size_t s = 0) {mSize=s;mArray = new int[mSize];}
        ~A()             {delete [] mArray;}

         // Copy constructor needs more work
         A(A const& copy)
         {
             mSize  = copy.mSize;
             mArray = new int[copy.mSize];

             // Don't need to worry about copying integers.
             // But if the object has a copy constructor then
             // it would also need to worry about throws from the copy constructor.
             std::copy(&copy.mArray[0],&copy.mArray[c.mSize],mArray);

         }

         // Define assignment operator in terms of the copy constructor
         // Modified: There is a slight twist to the copy swap idiom, that you can
         //           Remove the manual copy made by passing the rhs by value thus
         //           providing an implicit copy generated by the compiler.
         A& operator=(A rhs) // Pass by value (thus generating a copy)
         {
             rhs.swap(*this); // Now swap data with the copy.
                              // The rhs parameter will delete the array when it
                              // goes out of scope at the end of the function
             return *this;
         }
         void swap(A& s) noexcept
         {
             using std::swap;
             swap(this.mArray,s.mArray);
             swap(this.mSize ,s.mSize);
         }

         // C++11
         A(A&& src) noexcept
             : mSize(0)
             , mArray(NULL)
         {
             src.swap(*this);
         }
         A& operator=(A&& src) noexcept
         {
             src.swap(*this);     // You are moving the state of the src object
                                  // into this one. The state of the src object
                                  // after the move must be valid but indeterminate.
                                  //
                                  // The easiest way to do this is to swap the states
                                  // of the two objects.
                                  //
                                  // Note: Doing any operation on src after a move 
                                  // is risky (apart from destroy) until you put it 
                                  // into a specific state. Your object should have
                                  // appropriate methods for this.
                                  // 
                                  // Example: Assignment (operator = should work).
                                  //          std::vector() has clear() which sets
                                  //          a specific state without needing to
                                  //          know the current state.
             return *this;
         }   
 }
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

动态分配对象数组 的相关文章

  • C# 锁(mylocker) 不起作用

    我有很多 Web 服务调用 异步 在回调中 我会将结果绘制到 Excel 中 我想同步绘图方法 所以我使用以下内容 但是 从我在 Visual Studio 中追踪到 每次 lock locker 都会成功 并且有许多线程运行clearco
  • 了解 VerQueryValue

    在 MSDN 上 我注意到 VerQueryValue 函数的以下内容 lplp缓冲区 输出 低电压空洞当此方法返回时 包含指向 pBlock 指向的缓冲区中所请求版本信息的指针的地址 当关联的 pBlock 内存被释放时 lplpBuff
  • C++:Linux平台上的线程同步场景

    我正在为 Linux 平台实现多线程 C 程序 其中我需要类似于 WaitForMultipleObjects 的功能 在搜索解决方案时 我发现有一些文章描述了如何在 Linux 中实现 WaitForMultipleObjects 功能
  • C 语言中的套接字如何工作?

    我对 C 中的套接字编程有点困惑 You create a socket bind it to an interface and an IP address and get it to listen I found a couple of
  • MigraDoc 项目符号列表(漏洞)

    在我的解决方案中 我在 PDF 文件中使用项目符号列表 它看起来像这样 Solcellepaneler kr ver hverken autoriseret service eller tidskr vende vedligehold So
  • 如何在 C++ 中对四元结构进行有效排序?

    我有一个包含 x y z 和 w 成员的结构 如何高效排序 在 C 中首先按 x 然后按 y 按 z 最后按 w 如果你想实现字典排序 那么最简单的方法是使用std tie实现小于或大于比较运算符或函子 然后使用std sort http
  • 使用 strcpy 从整数生成指针,无需进行强制转换

    我不明白我做错了什么 我正在学习 C 很抱歉 如果这显然是错误的 但我正在尝试使用uthash http uthash sourceforge net 制作股票及其价格的哈希图 但是当我将股票添加到哈希映射时 我收到上述错误 我所做的就是从
  • 如何让BackgroundWorker返回一个对象

    我需要做RunWorkerAsync 返回一个List
  • 从 C++ 中的函数返回二维数组[重复]

    这个问题在这里已经有答案了 可能的重复 C 从函数返回多维数组 https stackoverflow com questions 3716595 c returning multidimension array from function
  • 用于轻松动态反射的 C# 库

    是否有任何库 例如开源项目等 可以更轻松地使用复杂的反射 例如动态创建对象或类 检查实例等 Thanks 有一个LinFu http www codeproject com KB cs LinFuPart1 aspx可用的库除了反射之外还可
  • C++在子类中调用虚方法

    我有以下课程 class A protected A inner public virtual void doSomething 0 class B public A void doSomething if inner NULL inner
  • C# While 循环与 For 循环?

    在 C 中 一个问题已经困扰我一段时间了 它的 While 和 For 循环之间的实际主要区别是什么 它只是纯粹的可读性吗 在 for 循环中本质上可以做的所有事情都可以在 while 循环中完成 只是在不同的地方 举这些例子 int nu
  • 如何使用 Linq to Sql 修剪值?

    在数据库中 我有一个名为 联系人 的表 名字和其他此类字符串字段设计为使用 Char 数据类型 不是我的数据库设计 我的对象 Contact 映射到属性中的字符串类型 如果我想做一个简单的测试 通过 id 检索 Contact 对象 我会这
  • 如何使用 HttpClient 验证 Pardot API

    我花了大约一天的时间尝试对 Pardot API 进行身份验证 它不喜欢我尝试发布消息正文的方式 所以我想发布对我有用的解决方案 如果您有任何建议或替代方案 我想听听 ServicePointManager SecurityProtocol
  • 获取RFC返回的嵌套结构的值?

    我是 C 新手 我有 rfc 它以嵌套结构的形式从 SAP 系统返回数据 但是当我使用以下方式获取该数据时 IrfcTable table rfc getTable exporting parameter et customer 它仅返回第
  • vs2010 c++ 通过debug查看指针内容

    我正在使用 Vs2010 c 处理 2D 数组 我从一维指针开始 并使用操作 如下 class CMatrix void clear public int nRows int nCols short MyMat CMatrix CMatri
  • 如何在PropertyGrid中自定义绘制GridItem?

    我想以与所有者在 ListView 详细信息 和其他控件中绘制项目类似的方式在 PropertyGrid 中绘制属性值 如果将属性声明为 Color 类型 则其值将使用字符串描述旁边的颜色样本来绘制 如果属性是图像类型 则在字符串描述旁边绘
  • 如何获取数字列的确切类型,包括。规模和精度?

    有没有办法知道列中列的确切类型DataTable 现在我正在这样做 DataTable st dataReader GetSchemaTable foreach DataColumn col in st Columns var type c
  • 比较 C# 中的对象属性[关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 Locked 这个问题及其答案是locked help locked posts因为这个问题是题外话 但却具有历史意义 目前不接受新的答案或互动
  • 通过开源 PCL 使用 API 查看 3D 点云

    我使用 ToF 飞行时间 相机来获取 XYZ 格式的深度数据 为了实现 3D 点云的可视化目的 我想使用开源 PCL 提供的 API 网址为http pointclouds org documentation tutorials pcl v

随机推荐

  • EOF 符号常量

    From C 编程语言 int c while c getchar EOF putchar c 解决办法是getchar当没有更多输入时 返回一个独特的值 该值不能与任何真实字符混淆 这个值称为EOF 表示 文件结束 我们必须声明c是一个足
  • gulp + 浏览器同步无法获取/错误

    我正在学习当前的前端构建系统 我想使用浏览器同步 问题是它不会在命令行中抛出错误 而是当它启动浏览器时 它不会显示我的html文件 并且它会在浏览器窗口中显示 无法获取 错误 这是我的 gulpfile js 代码 var gulp req
  • 电话链接在 iframe 中不起作用,但在 iOS 9 Web 中的 div 中起作用。如何使电话链接在 iOS 9 safari 中正常工作?

    您好 我正在尝试 iOS9 中 iframe 内的电话链接 iOS9 中的 safari 中无法打开手机应用程序 当我在里面尝试相同的链接时 它就在那里工作 我正在尝试下面的锚标记 将此代码放入 div 中时会打开手机应用程序 但同样的代码
  • 使用 元素通过 Wix 运行 SQL 脚本文件

    我是 Wix 安装程序的新手 我有一个要求 必须提供 SQL Server 登录凭据并从特定路径运行脚本 我不明白出了什么问题 项目已成功构建并创建了 msi 运行后我收到以下错误 错误26204 错误 2147217900 无法执行SQL
  • 如何在SAS中删除重复的记录\观察而不进行排序?

    我想知道是否有办法取消重复记录WITHOUT排序 有时候 我想保留原来的顺序 只想删除重复的记录 是否可以 顺便说一句 以下是我对不重复记录的了解 它最终会进行排序 1 proc sql create table yourdata nodu
  • JavaScript:异常排序

    假设我有一个对象数组 为了更简单的显示目的 我将其显示为数组 TEST NEW ALPHA ZOO WHATEVER 我需要按字母顺序对其进行排序 简单的部分 但是 我需要以某种方式对其进行排序 即某个单词 可以说NEW将会在最后结束 AL
  • 如何通过调用 HTTP API 网关 + Lambda(已使用 Amazon Cognito 用户池进行身份验证)获取用户详细信息

    用户登录 Amazon Cognito 应用程序 Web 会获取一个 访问令牌 每当调用 API 网关 HTTP API 或 REST API 时都会使用该令牌 API 网关配置为使用 Cognito 用户池作为授权者 因此如果 访问令牌
  • Spark:shuffle操作导致GC长时间暂停

    我在跑Spark 2我正在尝试洗牌大约 5 TB 的 json 我在洗牌期间遇到了很长的垃圾收集暂停Dataset val operations spark read json inPath as MyClass operations re
  • 如何在 PHP 中复制此 C# 哈希? (toByteArray()、ComputeHash())

    我正在尝试复制以下代码PHP 这是我必须与之交互的 API 的示例代码 API 和示例代码位于C 我的应用程序在PHP 5 3 我不是 C 开发人员 因此在执行此操作时遇到困难 C Code I am trying to replicate
  • 浮动操作按钮与最后一个卡片视图中的复选框重叠

    我有一个布局文件 其中包含 RecyclerView 和 FloatingActionButton 在里面我有多个 CardView 主要布局文件
  • 按索引从下拉列表中选择第一项不起作用。未绑定方法 select_by_index

    我正在尝试单击下拉列表中的第一项 我想使用它的索引值 因为该值每次都可能不同 对于这个特定的测试 我只需要选择下拉列表中的第一项 我尝试过 Select select by index 1 我收到错误 Traceback most rece
  • 您可以控制借用结构体还是借用字段吗?

    我正在开发一个涉及以下结构的程序 struct App data Vec
  • openGL转png

    我正在尝试将包含大量纹理 没有移动 的 openGL 编辑 我画的卡片 thx unwind 转换为一个 PNG 文件 我可以在框架的另一部分中使用该文件我正在与 有 C 库可以做到这一点吗 thanks 如果您的意思只是 获取由 Open
  • 用于编译/反编译二进制数据文件的通用实用程序或库?

    我有各种二进制文件格式 我需要将其转储为某种文本格式 编辑然后重新编译 可能是二进制格式的稍微不同的版本 当然 我可以用 C C 编写一堆实用程序代码来完成这种事情 并且可能利用一个库来处理文本方面的事情 XML 或 JSON 或其他 但这
  • mysql 查询中的 golang 切片,带有 where in 子句

    我正在运行以下查询 但只获取第一个 id 值 select from table where table id in 1 2 3 4 5 6 7 9 11 13 14 15 17 and table deleted at is null 我
  • AWS Api Gateway:缺少身份验证令牌

    所以我有一个链接到 lambda 函数的 api 网关的自定义域名设置 如果我这样做的话我就可以正常工作https api domain com something https api domain com something行为符合预期
  • Http Auth 不适用于 PHP

    我使用 Laravel Lumen Shield 扩展进行 Http 身份验证 但是在我的本地计算机上一切都很完美 我只在我们的服务器上遇到了问题 问题是在我提交正确的登录数据后 登录屏幕再次出现 我尝试了不同的登录数据 不同的浏览器 登录
  • 用于列出用户和组的 Python 脚本

    我正在尝试编写一个脚本 在自己的行上输出每个用户及其组 如下所示 user1 group1 user2 group1 user3 group2 user10 group6 etc 我正在为此用 python 编写一个脚本 但想知道如何做到这
  • 在Python中解析制表符分隔的文件

    我正在尝试在 Python 中解析一个制表符分隔的文件 其中与行开头分开的 k 个制表符的数字应该放入第 k 个数组中 除了逐行读取并执行简单解决方案将执行的所有明显处理之外 是否有内置函数可以执行此操作 或者有更好的方法 您可以使用the
  • 动态分配对象数组

    我有一个包含动态分配数组的类 例如 class A int myArray A myArray 0 A int size myArray new int size A Note that as per MikeB s helpful sty