【问题标题】:Allocating Memory to Structures using Operator new and sizeof使用运算符 new 和 sizeof 为结构分配内存
【发布时间】:2020-12-08 18:14:05
【问题描述】:

我知道这篇文章涉及的具体问题不止一个,这些问题并不理想,但它们与现实世界的问题相关。如果有人能解释为什么事情不起作用,这对我来说将是一个非常有益的学习练习。请感谢我是一个新手,正在尝试使用 VS2019 处理一些遗留的 C++ 控制台代码。

旧代码使用具有成员的类,这些成员使用 malloc 单独分配内存,我理解这是用于 C 的,我应该对 C++ 使用 new 和 delete。我想知道为什么我尝试使用“operator new”和“sizeof”分配内存不起作用,以及我简化代码的尝试是否过于乐观。我在这方面花了很多时间,并试图浓缩问题,使问题得到清晰的编码和注释。我看到的问题本质上是:

  1. 如何使用 sizeof 以字节为单位返回结构或类的真实内存需求,并在运行时通过用户输入分配内存(我只能返回类/结构指针的大小,而不是取消引用的总字节数指向)?

  2. 如何在运行时使用 (1) 的倍数给定用户输入:即 (sizeof(*structure) * x) 来正确分配内存?

  3. 成功分配内存后;如何在不费力地循环每个成员变量的情况下复制结构中的字段范围:对于指针引用具有不同字节数的不同类型的字段,这是否可能?

感谢您的帮助!

#include <iostream>     // std::cout
#include <new>          // ::operator new
#include <iostream>     // std::cout
#include <algorithm>    // std::copy
#include <vector>       // std::vector

//  define structure "part"
struct part {
int* sprocket;
int* bolt;
double* cost;
double* postage;
double* packing;
double* insurance;
};
// define class "parent"
class parent {
public:
int* phone;
part* variable;
};

int main()
{

using namespace std;

// declare pointers
parent *father, *mother;
part *copy;

int size1, size2, size3, size4, size5, size6, size7, size8;
int i, l;

// get length variable at runtime
cout << "enter length" << endl;
cin >> l;

// fetch individual pointer variable sizes in bytes
size1 = sizeof(*father->variable->sprocket);    // size of int
size2 = sizeof(*father->variable->bolt);        // size of int
size3 = sizeof(*father->variable->cost);        // size of double
size4 = sizeof(*father->variable->postage);     // size of double
size5 = sizeof(*father->variable->packing);     // size of double
size6 = sizeof(*father->variable->insurance);   // size of double
size7 = sizeof(*father);                        // size of total struct
size8 = sizeof(*copy);                          // size of total struct
// print these to console for checking
cout << "sizes in bytes"                         << endl;
cout << "sizeof int sprocket is:"       << size1 << endl;
cout << "sizeof int bolt is:"           << size2 << endl;
cout << "sizeof double cost is:"        << size3 << endl;
cout << "sizeof double postage is:"     << size4 << endl;
cout << "sizeof double packing is:"     << size5 << endl;
cout << "sizeof double insurance is:"   << size6 << endl;
cout << "sizeof 'father' is:"           << size7 << endl;
cout << "sizeof 'copy' is:"             << size8 << endl;

//  This is the output to the console:

//  enter length
//  10
//  sizes in bytes
//  sizeof int sprocket is : 4
//  sizeof int bolt is : 4
//  sizeof double cost is : 8
//  sizeof double postage is : 8
//  sizeof double packing is : 8
//  sizeof double insurance is : 8
//  sizeof 'father' is : 8
//  sizeof 'copy' is : 24


/* cannot work out a way of finding total number of bytes associated with
structure or class /*

/* I want to avoid doing this!!! */

//father->phone             = (int*)malloc(sizeof(int) * l);
//father->variable->bolt    = (int*)malloc(sizeof(int) * l);
//father->variable->................... etc etc etc

/* and instead do this */

father = (parent*) :: operator new (sizeof(parent) * 2 * l);
if (father == NULL)
cout << "error assigning memory to variable." << endl;

copy = (part*) :: operator new (sizeof(part) * l);
if (copy == NULL)
cout << "error assigning memory to copy." << endl;

/*  but cannot seem to get the memory assignment right!!! 
and get a "write access violation" here which I'm certain 
is due to the "new" allocation above  */

/* this loop only to populate data in "father" to check memory
allocation and data for checking copying later*/    
for (i = 0; i < (2 * l); i++) {
father->phone[i]                = i;
father->variable->sprocket[i]   = i;
father->variable->bolt[i]       = i;
father->variable->cost[i]       = i * 0.3; // multiply by 0.3 to give double
father->variable->postage[i]    = i * 0.3; // multiply by 0.3 to give double
father->variable->packing[i]    = i * 0.3; // multiply by 0.3 to give double
father->variable->insurance[i]  = i * 0.3; // multiply by 0.3 to give double
}

/*  I wish to copy a range (in this example half user input l) from 
the "part" structure of "father" to the part structure 
pointed to by "copy" but would like to do it elegantly 
as follows rather than loop through each 
member pointer.
        
I'd like to assign the new pointer "copy" to another "parent" object 
later in code.  This avoids a lot of complication in further modifying 
the legacy code hence cannot pass class object as argument 3*/

//std::copy(father->variable, father->variable + (l/2), copy.begin());

// later in code.........

//initialize "mother"
//mother->variable = copy;

}

【问题讨论】:

  • 你已经#include &lt;vector&gt;,你为什么要开始手动处理new?此外,所有这些指向类中普通成员变量的指针看起来都很奇怪。你为什么在那里使用指针?这些是std::vector&lt;double&gt; 成员吗?
  • 对不起,如果这不合适:就像我说的我在学习。
  • 恐怕你需要从头开始,彻底重新思考你的班级设计。尽量不使用指针。
  • 恐怕你的 cmets 不是很有帮助。您可以将此处发布的所有内容回复为“从头开始”。如果我一开始就能够做到这一点,我就不需要寻求帮助。您能帮我解决如何将正确的 sizeof 变量传递给内存分配的问题吗?指针代表我正在使用的代码:我必须处理这样的安排。
  • 你对我的印象让你误会了。我真的说这非常罕见,但你所拥有的看起来很糟糕,我相信最好重新开始。对于初学者,我认为part 应该看起来像:struct part { int sprocket; int bolt; double cost; double postage; double packing; double insurance; };,在那里使用指针实际上是没有意义的(除非你能有充分的理由解释)。

标签: c++ data-structures new-operator copy-constructor


【解决方案1】:

malloc() 仅处理原始字节。 new 处理对象,new[] 处理对象数组。对象的大小由编译器为您处理,因此您根本不需要手动使用sizeof(),即C中的这些语句:

father->phone             = (int*)malloc(sizeof(int) * l);
father->variable->bolt    = (int*)malloc(sizeof(int) * l);
father->variable->................... etc etc etc

...

free(father->variable->................... etc etc etc);
free(father->variable->bolt);
free(father->phone);

将在 C++ 中使用 new[] 转换为:

father->phone             = new int[l];
father->variable->bolt    = new int[l];
father->variable->................... etc etc etc

...

delete[] father->variable->................... etc etc etc;
delete[] father->variable->bolt;
delete[] father->phone;

但是,您确实应该考虑直接使用std::vector 而不是new[]。让它为你处理内存管理。

【讨论】:

  • 非常好:感谢 Remy,这正是我正在寻找的解决这个问题的方向。我正在尝试使用旧代码,其中一些很可能是用 C 编写的,所以这可能是我对不同内存分配方法的一些误解的原因:感谢!
  • 您显示的代码非常复杂且容易出错,我同意 πάνταῥεῖ 的观点,它确实需要从头开始重写。 C++ 不是 C,在 C 中完成的某些事情在 C++ 中以更好的方式处理。 避免直接使用new 就是其中之一。尽可能使用自动存储而不是动态存储。在处理动态数组/列表时使用标准容器。手动管理动态资源时使用构造函数和析构函数。
  • 我发布的代码是试图从一个更大的项目中获取元素,并以非常基本的表示形式呈现我的逻辑。最初的项目是很久以前由其他人编写的,它使用了使用 malloc、realloc 等操作内存的类,并广泛使用指针来存储/操作大型数据集。我正在为这个旧代码添加设施,同时也在学习编程!如果这看起来有点像车祸,我向你和 πάνταῥεῖ 道歉,但我已经学会使用更现代的工具,所以它已经值得了!
猜你喜欢
  • 2012-11-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多