C++对象数组的声明和初始化

Shipper-LI 2013-10-06 03:54:12
我想声明一个对象数组,然后在函数中再分别初始化。现在的问题是不知道怎么初始化,请教高手该怎么办?急急
...全文
10962 26 打赏 收藏 转发到动态 举报
写回复
用AI写文章
26 条回复
切换为时间正序
请发表友善的回复…
发表回复
Shipper-LI 2013-10-13
  • 打赏
  • 举报
回复
谢谢大家,我现在用指针给数组赋值。
  • 打赏
  • 举报
回复
引用 17 楼 unituniverse2 的回复:
[quote=引用 15 楼 wangdahu888 的回复:] 可以这样来

#include <iostream>

class A
{
private :
    int _n;
public:
    A( int n):_n(n) {}
};

int main()
{
    A *pA = (A*) operator new (sizeof(A) * 10);
    for(int i = 0; i != 10; ++i)
    {
        new (pA + i) A(i);
    }
}

默认的对齐是4(32位下),但是有可能A要求8字节的对齐(比如其中含有long long数据成员)。这时候这个new返回的地址经常不能满足[/quote] 类对象本身就内存对齐了,管返回地址,何事呀!!
unituniverse2 2013-10-08
  • 打赏
  • 举报
回复
operator new (sizeof(A) * 10) 不带类型的分配(sizeof(A)里面的A是不会反映到new的类型的,仅仅代表了大小信息),其实等同于 new BYTE [sizeof(A) * 10];默认的对象对齐以字节类型为准而不是待分配的类类型要求的基址对齐方式
unituniverse2 2013-10-08
  • 打赏
  • 举报
回复
引用 18 楼 wangdahu888 的回复:
[quote=引用 17 楼 unituniverse2 的回复:] [quote=引用 15 楼 wangdahu888 的回复:] 可以这样来

#include <iostream>

class A
{
private :
    int _n;
public:
    A( int n):_n(n) {}
};

int main()
{
    A *pA = (A*) operator new (sizeof(A) * 10);
    for(int i = 0; i != 10; ++i)
    {
        new (pA + i) A(i);
    }
}

默认的对齐是4(32位下),但是有可能A要求8字节的对齐(比如其中含有long long数据成员)。这时候这个new返回的地址经常不能满足[/quote] 类对象本身就内存对齐了,管返回地址,何事呀!![/quote] 想太多了。我说的对齐是整个对象的起始地址 要知道对齐的根本目的是为了让处理器取值(单个整型)的时候能一条指令整个的取。 这样就需要类或结构体每个成员都对齐。而这种保证需要同时满足成员对对象基地址的对齐和整个对象基地址本身的对齐,如果后者不满足的话其实还是算没有对齐的。
unituniverse2 2013-10-08
  • 打赏
  • 举报
回复
还有A本身的大小问题,大小对齐正是为了在定义数组的时候不至于存在部分数组元素没有对齐的问题。比如 class A { char m1; int m2; char m3; }; 如果是为了压缩空间,完全可以让sizeof(A)等于9。但是这样一来如果定义A a[4];的话将会出现除了a[0]其余元素都未有对齐的情况。所以A的末尾也补一些字节从而让sizeof(A)等于3个int的字节大小
unituniverse2 2013-10-08
  • 打赏
  • 举报
回复
引用 21 楼 wangdahu888 的回复:
[quote=引用 20 楼 unituniverse2 的回复:] operator new (sizeof(A) * 10) 不带类型的分配(sizeof(A)里面的A是不会反映到new的类型的,仅仅代表了大小信息),其实等同于 new BYTE [sizeof(A) * 10];默认的对象对齐以字节类型为准而不是待分配的类类型要求的基址对齐方式
不对吧,sizeof(A)本身的大小,就已将对齐考虑在内了[/quote] sizeof(A)只是一个整数了。不会决定new返回的指针的对齐。比如下面这个例子

#include <iostream>
 
class A
{
private :
    long long _n;
public:
    A( long long n):_n(n) {}
};
 
int main()
{
    A *pA = (A*) operator new (sizeof(A) * 10);
    for(int i = 0; i != 10; ++i)
    {
        new (pA + i) A(i);
    }
}
sizeof(A)等于8,这样new执行的时候相当于 operator new (80); 而他的返回值在32位系统中默认对齐为4,也就是整个new在你强制转换成A*之前的返回值是被4整除的,实际上按语法看的话甚至有可能仅是1,也就是完全不考虑对齐。而A对象要求以8为整个对象的对齐,也就是整个new在你强制转换成A*之前的返回值能被8整除。如果是new A的话,(void *)new A的结果保证能被8整除而如果系统找不到这样的空闲地址区域的话宁可失败,而不是返回一个没有对齐的地址。而这样的约束对于(void *)operator new (80);却并不成立。 你说的A“已经考虑了对齐”其实应该指的仅是成员相对于对象基址的对齐,也就是说如果A是这样的: class A { char m1; int m2; }; 那么在m1到m2之间会有诺甘个字节的空缺(共sizeof(int)-1个字节)而不是让m2紧挨着m1存放。 但是涉及到内存分配,不管是直接定义也好还是用new分配,不光需要你说的这种对齐,而且还需要整个对象的基地址的对齐。这样才能最终做到每个成员在运行时真正的对齐。如果是直接定义或者用new类型的分配方式,这总是可以保证;但是去掉类型信息分配的话就没有这种保证了
MZstudio2012 2013-10-08
  • 打赏
  • 举报
回复
如果你定义的数组的对象类型有默认构造函数,那么恭喜你,在数组用到的时候初始化自动完成; 如果没有的话,比如有一个单参数的构造函数,那么你必须显式调用。比如 class A { private: int a; public: A(aa):a(aa){} }; A arr[2] = { A(1), A(2) }; 希望对你有所帮助
mujiok2003 2013-10-08
  • 打赏
  • 举报
回复
std::vector/std::array
  • 打赏
  • 举报
回复
引用 20 楼 unituniverse2 的回复:
operator new (sizeof(A) * 10) 不带类型的分配(sizeof(A)里面的A是不会反映到new的类型的,仅仅代表了大小信息),其实等同于 new BYTE [sizeof(A) * 10];默认的对象对齐以字节类型为准而不是待分配的类类型要求的基址对齐方式
不对吧,sizeof(A)本身的大小,就已将对齐考虑在内了
ljhhh0123 2013-10-07
  • 打赏
  • 举报
回复
在对象声明里写个init()函数,随后一个个的调用.
unituniverse2 2013-10-07
  • 打赏
  • 举报
回复
引用 15 楼 wangdahu888 的回复:
可以这样来

#include <iostream>

class A
{
private :
    int _n;
public:
    A( int n):_n(n) {}
};

int main()
{
    A *pA = (A*) operator new (sizeof(A) * 10);
    for(int i = 0; i != 10; ++i)
    {
        new (pA + i) A(i);
    }
}

默认的对齐是4(32位下),但是有可能A要求8字节的对齐(比如其中含有long long数据成员)。这时候这个new返回的地址经常不能满足
youkuxiaobin 2013-10-07
  • 打赏
  • 举报
回复
给类写一个initialize函数
  • 打赏
  • 举报
回复
可以这样来

#include <iostream>

class A
{
private :
    int _n;
public:
    A( int n):_n(n) {}
};

int main()
{
    A *pA = (A*) operator new (sizeof(A) * 10);
    for(int i = 0; i != 10; ++i)
    {
        new (pA + i) A(i);
    }
}

「已注销」 2013-10-07
  • 打赏
  • 举报
回复
用 allocator<T>
缘来是你a 2013-10-06
  • 打赏
  • 举报
回复
这是我写的一个程序,有对象数组 #include<iostream.h> class Book{ public: void input(int x) { qu=x; price=10*qu; } void product() { cout<<"qu*price="<<qu*price<<endl; } private: int qu,price; }; int main() { Book A[5]; int i; for(i=0;i<5;i++) { A[i].input(i+1); A[i].product(); } return 0; }
unituniverse2 2013-10-06
  • 打赏
  • 举报
回复
这种情况还是建议用STL里的数据结构。 默认的直接写编译器内置数组方式的定义仅支持定义的时候就完成初始化(后面再改内容就叫赋值而不是初始化了,达不到目的)。 placement new建议尽量少用或不用。除非你本来就是开发库代码。因为如果要用placement new,也得用placement delete,而且对象的生存期编译器就不再负责了,得你自己手动管理。而且placement new涉及的输入地址并不是能随意给的,一般要预先对齐,对齐边界得根据你new时候的对象的类型临时的给定。那这样看的话还不如干脆用stl的vector或者array模板得了,因为期间涉及到的数组元素处理的相关代码就算你不用stl而是自己写,功能上都差不多,但是对于不同的对象类型又不能通用,等于是需要自己一遍又一遍的实现功能上类似stl的代码。临时写的作品和别人几年专门针对性的维护的东西相比,哪个更好?不说自明的
unituniverse2 2013-10-06
  • 打赏
  • 举报
回复
这一直是个麻烦事。。。
HarryHanWang 2013-10-06
  • 打赏
  • 举报
回复
1、数组类型一旦声明,将自动调用默认构造函数初始化各个对象 2、一旦初始化之后,之后的只能是赋值 3、可以用 vector<T> 来声明容器,代替数组 4、可以用 allocator<T> 分配内存空间,然后用 allocator<T>::construct() 或 placement new 初始化,将内存分配与初始化分开 这一部分详见 《C++ primer 4th Edition P632 优化内存分配》
  • 打赏
  • 举报
回复
需要一个元素一个元素赋值,或者用 memcpy(dest, src, size);
zhaokai115 2013-10-06
  • 打赏
  • 举报
回复
C++11支持了吧
加载更多回复(6)

64,654

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧