对象数组与新对象
Array of objects vs new
#include <iostream>
class A {
public:
A(int d) : y(d) {}
int y;
};
int main(void) {
A d[3] = {A(0), A(1), A(2)};
std::cout << d[1].y << std::endl;
};
我正在为大学做一个项目。我被指示而不是使用对象数组,并用我类的临时对象实例化每个元素——所以类似上面代码的东西是否定的。相反,建议我们使用A*
类型的数组,然后在每个元素上使用new,这样我们就可以创建一个对象,并使每个元素指向它。
所以我们会有这样的东西:
A* d[3];
for (int i=0;i<3;i++)
d[i]=new A(i);
然而,与第一个版本相比,我不太理解实践中的差异。据我所知,在第一个版本中,我们使用构造函数创建了三个临时对象(它们是右值(,然后将它们分配给数组。赋值结束后,临时对象将被销毁,其值将复制到数组中。在第二个版本中,我们的优点是可以删除d[]
指向的内容,但忽略这一点,使用第一种方法的缺点是什么?
编辑:
class B{
public:
A a1[3];
}
假设我的初始定义后面跟着这个(A不是默认的可构造的,这样的东西是不可能的吗?所以在这种情况下,我不能使用对象数组,而是必须使用类型为A*
的指针数组,然后使用new
,作为我唯一的手段。
指针数组->创建对象并将其分配给指针时的内存分配。1000个指针的数组,其中有1个元素=内存的1倍。
对象数组->创建数组时的内存分配。内部有1个元素的1000数组=1000倍内存。
1(A d[3]
,它创建了一个内置数组(或C样式、纯数组、裸数组…(,其中包含(三个(A
类型的元素,这些元素存在于堆栈中(根据您的代码(。
2(A* d[3];
,它创建了一个内置数组,该数组包含指向类型为A
的元素(或者它们应该是(的(三个(指针。这并不意味着指向的元素是A
类型的,创建这些元素是开发人员的任务,您可以通过两种方式来完成,使用堆栈(如前所述(:
A element;
...
d[0] = &element;
或者使用堆(具有new
/new[]
和delete
/delete[]
(:
d[0] = new A;
...
delete d[0];
第二个选项的副作用;您可能指向一个已经损坏的元素(即元素超出范围(,因此可能存在seg故障;您可能会丢失指向已分配内存的指针(即指针数组超出范围,并且已分配内存尚未释放(,从而导致内存泄漏。
然而,一个优点是你可以使用惰性初始化(你不需要为你不使用的东西付费(。如果您不需要d[2]
中的A
对象(或由指向(,为什么要创建它并浪费内存?在这里出现了智能指针,它们让你的生活更轻松,只允许你在需要的时候分配内存,降低了seg故障(值得一提的是std::weak_ptr(、内存泄漏等的风险:
std::unique_ptr<A> d[3];
d[0] = std::make_unique<A>(); // Call make_unique when you need it
但仍然有点令人讨厌,内置阵列很好,但在某些情况下可能会更好。添加或删除元素、迭代、获取大小、访问尾部/头部等都很困难。这就是为什么容器非常有用的原因,即std::array
或std::vector
(在编译时不必知道其大小(:
std::vector<std::unique_ptr< A> > d(3);
std::array<std::unique_ptr<A,3> > d;
C++中的以下代码没有任何优势:
A* d[3];
for (int i=0;i<3;i++)
d[i]=new A(i);
事实上,你根本不应该写它。
使用本地声明的临时数组的解决方案是有效的,但有一个显著的限制,即要求数组中的元素数量为编译时间常数(即提前已知(。
如果您需要一个只有在运行时才知道的具有动态元素数的数组,那么您应该使用std::vector
,它会自动执行new
分配。这是C++中处理动态分配数组的惯用方法。
- 当一个新对象被分配到它的地址时,对象是否必须被销毁
- C++ 如何在将新对象分配给另一个对象时创建新对象
- 重用对象与创建新对象
- C++,创建新对象时类的对象更改
- 运算符重载 += 添加新对象
- 如何在运行时在对象数组中动态追加新对象C++并打印它们
- 从使用概念定义的函数返回新对象
- 从 Rcpp 函数返回指向"新"对象的指针的正确方法
- 如何删除派生类中基类对象的新对象
- 有没有一种方法可以从函数中返回一个新对象或对现有对象的引用
- 为模板参数类型中的新对象分配内存
- 删除通过取消引用新对象初始化的对象
- C++ 实例化新对象时不接受继承方法默认参数值
- 有没有办法删除传递给函数"foo(新对象())"的对象?
- 将 Eigen::MatrixXd 转换为 arma::mat 并在新对象上制作副本
- 创建新对象并立即为其设置属性时出现编译器错误
- 如何异步销毁对象并立即分配一个新对象
- 删除传递给 C++ 中成员函数的新对象
- 具有构造函数的新对象数组,需要在C++中设置参数
- 我可以制作一个对象方法,如果单独调用,它将自行修改,但如果在复制初始化期间调用,则会返回一个新对象?