c++中关于初始化对象数组的问题

szyangzhen 2009-09-27 11:00:08
我正在学c++,正在看c primer plus中文第四版。在其中297页遇到一个问题。

那书上说:
初始化对象数组的方案是,首先使用默认构造函数创建数组元素,然后花括号中的构造函数将创建临时对象,然后临时对象的内容复制到相应的元素中。因此要创建类对象数组,则这个类必须有默认构造函数。

但是我写一个检测这句话的程序,却不是上面说的那样的。

这是头文件
#include <iostream>
using namespace std;

class example
{
private:
char *s;
public:
example(const char *);
~example();
void show() {cout << s << endl;};
};




这是类方法实现文件
#include "class.h"
#include <cstring>
example::example(const char *p)
{
s = new char[strlen(p) + 1];
strcpy(s,p);
}
example::~example()
{
delete [] s;
}



这是主函数
#include "class.h"
int main(void)
{
example ex[4] = {example("hello"),example("hi"),example("yeah"),example("good")};
for (int i = 0; i < 4; i++)
ex[i].show();
return 0;
}

我用g++编译运行成功,结果是
hello
hi
yeah
good



但是这与我预想的结果不一样。首先,其中没有默认构造函数,生成类对象数组,也没有报错。
其次,书上说是生成一个临时对象再复制,但我这个函数构造函数中用了new,析构函数也用了delete.
生成的临时对象应该只复制了s这个成员中的内容,而其指向的字符串应该被delete了,但结果还是显示了,没出错。



不知道是书错了,还是我弄错了,希望大家帮我看看。谢谢

~
...全文
862 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
rogyl 2010-12-28
  • 打赏
  • 举报
回复
书上也没错,答案是对的,如果你理解C数组的话,就应该知道这个没有调用复制构造函数;这种方式和
example e[] = new example[5555]这种方式是不一样的
szyangzhen 2009-09-28
  • 打赏
  • 举报
回复
谢谢各位的回答,我自己又验证了下,上面的在vc上也能通过,应该是书上错了。楼上的这位,我用vc试了下你所说,你那种情况需要三个构造函数,默认构造函数,带参的构造函数(非复制构造函数),还是等号赋值操作符。
孟俊 2009-09-28
  • 打赏
  • 举报
回复
这里是直接使用指定的构造函数进行的初始化,并没有先用默认的构造函数,然后再执行拷贝构造。

书上的意思应该是如果使用下面的方法写代码,则一定需要默认的构造函数和copy construction了

A a[10];
a[0] = A(1);
a[1] = A(2);
......

cphj 2009-09-28
  • 打赏
  • 举报
回复
事实证明要么书上错了,要么VC编译器不遵循规范

我加上默认构造器,运行代码却没有被调到

我个人倾向于怀疑书上错了,因为这种调用2次构造器的思想与C++的注重效率的设计原则相矛盾
class example 
{
private:
char *s;
public:
example()
{
cout << "In example()" << endl;
}
example(const char *);
~example();
void show() {cout << s << endl;};
};
hnoe 2009-09-28
  • 打赏
  • 举报
回复
编译器视情况会生成缺省构造函数
xiaotechshen 2009-09-28
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 underuwing 的回复:]
借宝地一问,为什么s = new char[strlen(p) + 1]这句中要strlen(p) + 1呢?strlen(p)不可以么?
[/Quote]

不可以,你得为‘\0’预留空间,strlen只是P得长度
underuwing 2009-09-28
  • 打赏
  • 举报
回复
借宝地一问,为什么s = new char[strlen(p) + 1]这句中要strlen(p) + 1呢?strlen(p)不可以么?
2009-09-27
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 arong1234 的回复:]
所以我说这依赖于编译器怎么翻译用对象数组初始化对象数组的情况。这种不调用拷贝构造函数的初始化方式是比较理想的构建方式,但是很多编译器根本不支持,我估计这也不是C++标准内的,而是g++做的扩展(不过我从来不研究标准,因此不知道我的猜测对不对)
[/Quote]
这应该不属于优化的范畴,因为这会有严重的边缘效应(就如此例)。关键是显式调用一个构造函数到底是什么意义。(即 example("hello") 究竟是什么含义)
arong1234 2009-09-27
  • 打赏
  • 举报
回复
所以我说这依赖于编译器怎么翻译用对象数组初始化对象数组的情况。这种不调用拷贝构造函数的初始化方式是比较理想的构建方式,但是很多编译器根本不支持,我估计这也不是C++标准内的,而是g++做的扩展(不过我从来不研究标准,因此不知道我的猜测对不对)
[Quote=引用 5 楼 hpsmouse 的回复:]
事实证明,g++ 并没有调用拷贝函数~~
C/C++ code#include<iostream>
#include<cstring>usingnamespace std;class example
{private:char*s;public:
example(constchar*);
example(exampleconst& ano){cerr<<"copy constructor called"<<endl;}~example();void show() {cout<< s<< endl;};
};
example::example(constchar*p)
{
cerr<<"construct"<<this<<endl;
s=newchar[strlen(p)+1];
strcpy(s,p);
}
example::~example()
{
cerr<<"delete"<<this<<endl;
delete [] s;
}int main(void)
{
example ex[4]= {example("hello"),example("hi"),example("yeah"),example("good")};for (int i=0; i<4; i++)
ex[i].show();return0;
}
输出:
Assembly codeconstruct 0x7ffff1528880
construct 0x7ffff1528888
construct 0x7ffff1528890
construct 0x7ffff1528898
hello
hi
yeah
good
delete 0x7ffff1528898
delete 0x7ffff1528890
delete 0x7ffff1528888
delete 0x7ffff1528880
[/Quote]
kakashi0309 2009-09-27
  • 打赏
  • 举报
回复
因此要创建类对象数组,则这个类必须有默认构造函数。

这个应该是针对初始化可能不完全的情况

即example ex[4] = {example("hello"),example("hi"),example("yeah")};

2009-09-27
  • 打赏
  • 举报
回复
事实证明,g++ 并没有调用拷贝函数~~
#include <iostream>
#include <cstring>
using namespace std;

class example
{
private:
char *s;
public:
example(const char *);
example(example const& ano){cerr<<"copy constructor called"<<endl;}
~example();
void show() {cout << s << endl;};
};
example::example(const char *p)
{
cerr<<"construct "<<this<<endl;
s = new char[strlen(p) + 1];
strcpy(s,p);
}
example::~example()
{
cerr<<"delete "<<this<<endl;
delete [] s;
}
int main(void)
{
example ex[4] = {example("hello"),example("hi"),example("yeah"),example("good")};
for (int i = 0; i < 4; i++)
ex[i].show();
return 0;
}

输出:
construct 0x7ffff1528880
construct 0x7ffff1528888
construct 0x7ffff1528890
construct 0x7ffff1528898
hello
hi
yeah
good
delete 0x7ffff1528898
delete 0x7ffff1528890
delete 0x7ffff1528888
delete 0x7ffff1528880
arong1234 2009-09-27
  • 打赏
  • 举报
回复
你没理解人家的意思,他这种情况还需要两个构造函数(一个是不带参数的缺省构造函数,还有一个拷贝构造函数)

[Quote=引用 3 楼 kakashi0309 的回复:]
  你这不是有构造函数嘛...

  析构函数是最后才调用的
[/Quote]
kakashi0309 2009-09-27
  • 打赏
  • 举报
回复
你这不是有构造函数嘛...

析构函数是最后才调用的
arong1234 2009-09-27
  • 打赏
  • 举报
回复
个人感觉这依赖编译器怎么翻译用“数组”初始化“对象数组”,也许是编译器相关,而你的g++扩展了
renyinick2 2009-09-27
  • 打赏
  • 举报
回复
学一下~~

64,631

社区成员

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

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