using namespace std;
#include"student.h"
//类声明:
class student
{
private:
int num;
public:
student();
~student();
int getnum();
};
//成员函数实现:
student::student()
{
int num = 100;
}
int student::getnum()
{
return num;
}
student::~student(){}
//主函数:
int main()
{
student *stu;
stu = new student[];
cout << stu->getnum() << endl;
stu->student::student();
cout << stu->getnum() << endl;
return 0;
}
两次输出的结果都是-33606819,说明new分配了内存空间后没有调用构造函数进行初始化。
怎样才能new以后调用构造函数初始化对象呢?
我印象中new了空间之后就应该调用构造函数了,但现在看来不是这样。
那new和构造函数之间又是什么关系呢?请各位指教。
23 个解决方案
#1
构造函数里面的变量num不是student类的成员变量,局部变量屏蔽掉了成员变量
student::student()
{
num = 100;
}
改成这样就行了
student::student()
{
num = 100;
}
改成这样就行了
#2
怎么可能没有调用构造函数呢 除非遇到异常
new操作符有两个动作
1 调用operator new函数
2 调用相关的构造函数
遇到异常会回滚
new操作符有两个动作
1 调用operator new函数
2 调用相关的构造函数
遇到异常会回滚
#3
lz记忆中的正确结论被个错误程序推翻了 呵呵 太粗心了
#4
有2个错误:
(1)动态分配类类型数组时未有分配大小;
stu = new student[]; -》stu = new student[2];
(2)student::student()
{
int num = 100;
} 这个构造函数将num定义为局部变量,覆盖了成员那个num,成员那个num并未初始化;
输出:100
(1)动态分配类类型数组时未有分配大小;
stu = new student[]; -》stu = new student[2];
(2)student::student()
{
int num = 100;
} 这个构造函数将num定义为局部变量,覆盖了成员那个num,成员那个num并未初始化;
#include <iostream>
using namespace std;
//类声明:
class student
{
private:
int num;
public:
student();
~student();
int getnum();
};
//成员函数实现:
student::student()
{
num = 100;
}
int student::getnum()
{
return num;
}
student::~student(){}
//主函数:
int main()
{
student *stu;
stu = new student[2];
cout << stu->getnum() <<endl;
return 0;
}
输出:100
#5
#include <iostream>
using namespace std;
//#include"student.h"
//类声明:
class student
{
private:
int num;
public:
student();
student(int);
~student();
int getnum();
};
//成员函数实现:
student::student():num(0) //无参构造函数,通过初始化列表来消除垃圾数据
{
}
student::student(int x)//我又定义了一个带一个参数的构造函数
{
num=x;
}
int student::getnum()
{
return num;
}
student::~student(){}
//主函数:
int main()
{
student *stu;
stu = new student;//你这里大可不必写成stu=new student[];去掉[]即可
//cout < < stu->getnum() < < endl;//这里有错,因为你只是声明了*stu,并没有初始化它,初始化一个类的对象只
//能通过调用构造函数,stu本身是个指针,我们没有给指针提供的默认构造函数和自
//写的构造函数,这样你只是返回申请的指针的地址,但它指向不明,是个野指针,
//会返回垃圾数据,所以会输出-33606819
student p=student(100);
cout<<stu->getnum()<<endl;
*stu=student();
cout<<stu->getnum()<<endl;
return 0;
}
#6
int main()
{
student *stu;
stu = new student;//你这里大可不必写成stu=new student[];去掉[]即可
//cout < < stu->getnum() < < endl;//这里有错,因为你只是声明了*stu,并没有初始化它,初始化一个类的对象只
//能通过调用构造函数,stu本身是个指针,我们没有给指针提供的默认构造函数和自
//写的构造函数,这样你只是返回申请的指针的地址,但它指向不明,是个野指针,
//会返回垃圾数据,所以会输出-33606819
student p=student(100);
cout < <stu->getnum() < <endl;
*stu=student();
cout < <stu->getnum() < <endl;
return 0;
}
不好意思,不小心删掉了一行代码,在student p=student(100);和cout<<stu->getnum()<<endl;中间加上这行代码:*stu=p;或者stu=&p;,呵呵
{
student *stu;
stu = new student;//你这里大可不必写成stu=new student[];去掉[]即可
//cout < < stu->getnum() < < endl;//这里有错,因为你只是声明了*stu,并没有初始化它,初始化一个类的对象只
//能通过调用构造函数,stu本身是个指针,我们没有给指针提供的默认构造函数和自
//写的构造函数,这样你只是返回申请的指针的地址,但它指向不明,是个野指针,
//会返回垃圾数据,所以会输出-33606819
student p=student(100);
cout < <stu->getnum() < <endl;
*stu=student();
cout < <stu->getnum() < <endl;
return 0;
}
不好意思,不小心删掉了一行代码,在student p=student(100);和cout<<stu->getnum()<<endl;中间加上这行代码:*stu=p;或者stu=&p;,呵呵
#7
多谢了,确实这个地方粗心了。
#8
虽然经常来csdn,但是提问题还是第一次。想不到有这么多热心的朋友帮忙,非常感谢。
kxiaopeng 兄弟还给我逐行耐心解释,多谢。
kxiaopeng 兄弟还给我逐行耐心解释,多谢。
#9
刚才按照lzr4304061988012的做法,把对象数组的元素个数赋值stu = new student[2]也可以输出100了。
我就很奇怪,因为我原来是用while循环动态创建对象数组,相当于每循环一次创建一个对象,但运行不了。而这样赋值以后就可以运行了。为什么对象数组元素个数赋初值以后(赋值为1也可以),构造函数就可以将每个对象初始化了?这样就不是野指针了,不明白。
{这次还有一个收获,就是第一次这样用指针 stu->student::student(); cout << stu->getnum() << endl;
我把函数里面的int去掉以后,这一句也可以输出100}
我就很奇怪,因为我原来是用while循环动态创建对象数组,相当于每循环一次创建一个对象,但运行不了。而这样赋值以后就可以运行了。为什么对象数组元素个数赋初值以后(赋值为1也可以),构造函数就可以将每个对象初始化了?这样就不是野指针了,不明白。
{这次还有一个收获,就是第一次这样用指针 stu->student::student(); cout << stu->getnum() << endl;
我把函数里面的int去掉以后,这一句也可以输出100}
#10
你对构造函数不够了解,基础太差了!你要知道对象的生灭,构造函数是用来创建对象的,既然对象已经创建那么构造函数肯定被执行了,也就是先调用构造函数才能创建对象的;只要你执行了这个语句student *stu;
stu = new student[12];动态分配数组对象是要指定大小,其次这是已经产生了12个对象指针,他调用了12次构造函数,这不是野指针,他有自己的地址,他也不会造成非法访问;
stu = new student[12];动态分配数组对象是要指定大小,其次这是已经产生了12个对象指针,他调用了12次构造函数,这不是野指针,他有自己的地址,他也不会造成非法访问;
#11
你对构造函数不够了解,基础太差了!你要知道对象的生灭,构造函数是用来创建对象的,既然对象已经创建那么构造函数肯定被执行了,也就是先调用构造函数才能创建对象的;只要你执行了这个语句student *stu;
stu = new student[12];动态分配数组对象是要指定大小,其次这是已经产生了12个对象指针,他调用了12次构造函数,这不是野指针,他有自己的地址,他也不会造成非法访问;
stu = new student[12];动态分配数组对象是要指定大小,其次这是已经产生了12个对象指针,他调用了12次构造函数,这不是野指针,他有自己的地址,他也不会造成非法访问;
#12
楼上,你讲的只是其中一种情况,还有一种情况不调用构造函数。
所以,这样:
所以,这样:
student* stu = (student*)malloc (12*sizeof(student));
for(int i = 0; i < 12; i++)new(&stu[i])student;
#13
楼上的楼上讲的很好。
#14
只是楼主这种情况下,构造函数是必定调用。
如果遇到下面的情况,构造函数是不被调用的:
如果遇到下面的情况,构造函数是不被调用的:
class{
public:
string a;
float b;
};
#15
new数组只能调用默认构造函数
#16
你还没明白我的意思。如果我执行student *stu; stu = new student[];就如六楼所说:
《因为你只是声明了*stu,并没有初始化它,初始化一个类的对象只能通过调用构造函数,stu本身是个指针,我们没有给指针提供的默认构造函数和自写的构造函数,这样你只是返回申请的指针的地址,但它指向不明,是个野指针,会返回垃圾数据,所以会输出-33606819》
我也知道,既然student *stu; stu = new student[2];可以执行,那就一定是构造函数对他初始化了。
我不明白的是为什么赋初值的情况下对象数组就有了自己的地址,尽管我知道这是一个事实。
#17
2楼的说得很好。构造函数给变量初始化为他分配内存,而new也是为变量分配内存的,
两者的本质和关系实在是理不清,一团麻似的。还请各位指教。
#18
关键是当我们使用关键字new在堆上动态创建一个对象时,它实际上做了三件事: 获得一块内存空间、调用构造函数、返回正确的指针。当然,如果我们创建的是简单类型的变量,那么第二步会被省略。
例如:
class A
{
int i;
public:
A(int _i) :i(_i*_i) {}
void Say() { printf("i=%d\n", i); }
};
//调用new:
A* pa = new A(3);
那么上述动态创建一个对象的过程大致相当于以下三句话(只是大致上):
A* pa = (A*)malloc(sizeof(A));
pa->A::A(3);
return pa;
原因在于new至少有三中含义: new operator、operator new、placement new
#19
谁说构造函数是分配内存的?
#20
这个类也有默认构造函数,只是构造函数的初始化列表和函数体为空。
#21
补充一个错误:
内存泄露。。。
new分配后要delete
内存泄露。。。
new分配后要delete
#22
[code=C/C++]
#include <iostream>
using namespace std;
//类声明:
class student
{
private:
int num;
public:
student();
~student();
int getnum();
};
//成员函数实现:
student::student()
{
num = 100;
}
int student::getnum()
{
return num;
}
student::~student(){}
//主函数:
int main()
{
student *stu;
stu = new student;
cout << stu->getnum() <<endl;
return 0;
}[code=C/C++]
#include <iostream>
using namespace std;
//类声明:
class student
{
private:
int num;
public:
student();
~student();
int getnum();
};
//成员函数实现:
student::student()
{
num = 100;
}
int student::getnum()
{
return num;
}
student::~student(){}
//主函数:
int main()
{
student *stu;
stu = new student;
cout << stu->getnum() <<endl;
return 0;
}[code=C/C++]
#23
多谢各位了。终于可以结贴了。
#1
构造函数里面的变量num不是student类的成员变量,局部变量屏蔽掉了成员变量
student::student()
{
num = 100;
}
改成这样就行了
student::student()
{
num = 100;
}
改成这样就行了
#2
怎么可能没有调用构造函数呢 除非遇到异常
new操作符有两个动作
1 调用operator new函数
2 调用相关的构造函数
遇到异常会回滚
new操作符有两个动作
1 调用operator new函数
2 调用相关的构造函数
遇到异常会回滚
#3
lz记忆中的正确结论被个错误程序推翻了 呵呵 太粗心了
#4
有2个错误:
(1)动态分配类类型数组时未有分配大小;
stu = new student[]; -》stu = new student[2];
(2)student::student()
{
int num = 100;
} 这个构造函数将num定义为局部变量,覆盖了成员那个num,成员那个num并未初始化;
输出:100
(1)动态分配类类型数组时未有分配大小;
stu = new student[]; -》stu = new student[2];
(2)student::student()
{
int num = 100;
} 这个构造函数将num定义为局部变量,覆盖了成员那个num,成员那个num并未初始化;
#include <iostream>
using namespace std;
//类声明:
class student
{
private:
int num;
public:
student();
~student();
int getnum();
};
//成员函数实现:
student::student()
{
num = 100;
}
int student::getnum()
{
return num;
}
student::~student(){}
//主函数:
int main()
{
student *stu;
stu = new student[2];
cout << stu->getnum() <<endl;
return 0;
}
输出:100
#5
#include <iostream>
using namespace std;
//#include"student.h"
//类声明:
class student
{
private:
int num;
public:
student();
student(int);
~student();
int getnum();
};
//成员函数实现:
student::student():num(0) //无参构造函数,通过初始化列表来消除垃圾数据
{
}
student::student(int x)//我又定义了一个带一个参数的构造函数
{
num=x;
}
int student::getnum()
{
return num;
}
student::~student(){}
//主函数:
int main()
{
student *stu;
stu = new student;//你这里大可不必写成stu=new student[];去掉[]即可
//cout < < stu->getnum() < < endl;//这里有错,因为你只是声明了*stu,并没有初始化它,初始化一个类的对象只
//能通过调用构造函数,stu本身是个指针,我们没有给指针提供的默认构造函数和自
//写的构造函数,这样你只是返回申请的指针的地址,但它指向不明,是个野指针,
//会返回垃圾数据,所以会输出-33606819
student p=student(100);
cout<<stu->getnum()<<endl;
*stu=student();
cout<<stu->getnum()<<endl;
return 0;
}
#6
int main()
{
student *stu;
stu = new student;//你这里大可不必写成stu=new student[];去掉[]即可
//cout < < stu->getnum() < < endl;//这里有错,因为你只是声明了*stu,并没有初始化它,初始化一个类的对象只
//能通过调用构造函数,stu本身是个指针,我们没有给指针提供的默认构造函数和自
//写的构造函数,这样你只是返回申请的指针的地址,但它指向不明,是个野指针,
//会返回垃圾数据,所以会输出-33606819
student p=student(100);
cout < <stu->getnum() < <endl;
*stu=student();
cout < <stu->getnum() < <endl;
return 0;
}
不好意思,不小心删掉了一行代码,在student p=student(100);和cout<<stu->getnum()<<endl;中间加上这行代码:*stu=p;或者stu=&p;,呵呵
{
student *stu;
stu = new student;//你这里大可不必写成stu=new student[];去掉[]即可
//cout < < stu->getnum() < < endl;//这里有错,因为你只是声明了*stu,并没有初始化它,初始化一个类的对象只
//能通过调用构造函数,stu本身是个指针,我们没有给指针提供的默认构造函数和自
//写的构造函数,这样你只是返回申请的指针的地址,但它指向不明,是个野指针,
//会返回垃圾数据,所以会输出-33606819
student p=student(100);
cout < <stu->getnum() < <endl;
*stu=student();
cout < <stu->getnum() < <endl;
return 0;
}
不好意思,不小心删掉了一行代码,在student p=student(100);和cout<<stu->getnum()<<endl;中间加上这行代码:*stu=p;或者stu=&p;,呵呵
#7
多谢了,确实这个地方粗心了。
#8
虽然经常来csdn,但是提问题还是第一次。想不到有这么多热心的朋友帮忙,非常感谢。
kxiaopeng 兄弟还给我逐行耐心解释,多谢。
kxiaopeng 兄弟还给我逐行耐心解释,多谢。
#9
刚才按照lzr4304061988012的做法,把对象数组的元素个数赋值stu = new student[2]也可以输出100了。
我就很奇怪,因为我原来是用while循环动态创建对象数组,相当于每循环一次创建一个对象,但运行不了。而这样赋值以后就可以运行了。为什么对象数组元素个数赋初值以后(赋值为1也可以),构造函数就可以将每个对象初始化了?这样就不是野指针了,不明白。
{这次还有一个收获,就是第一次这样用指针 stu->student::student(); cout << stu->getnum() << endl;
我把函数里面的int去掉以后,这一句也可以输出100}
我就很奇怪,因为我原来是用while循环动态创建对象数组,相当于每循环一次创建一个对象,但运行不了。而这样赋值以后就可以运行了。为什么对象数组元素个数赋初值以后(赋值为1也可以),构造函数就可以将每个对象初始化了?这样就不是野指针了,不明白。
{这次还有一个收获,就是第一次这样用指针 stu->student::student(); cout << stu->getnum() << endl;
我把函数里面的int去掉以后,这一句也可以输出100}
#10
你对构造函数不够了解,基础太差了!你要知道对象的生灭,构造函数是用来创建对象的,既然对象已经创建那么构造函数肯定被执行了,也就是先调用构造函数才能创建对象的;只要你执行了这个语句student *stu;
stu = new student[12];动态分配数组对象是要指定大小,其次这是已经产生了12个对象指针,他调用了12次构造函数,这不是野指针,他有自己的地址,他也不会造成非法访问;
stu = new student[12];动态分配数组对象是要指定大小,其次这是已经产生了12个对象指针,他调用了12次构造函数,这不是野指针,他有自己的地址,他也不会造成非法访问;
#11
你对构造函数不够了解,基础太差了!你要知道对象的生灭,构造函数是用来创建对象的,既然对象已经创建那么构造函数肯定被执行了,也就是先调用构造函数才能创建对象的;只要你执行了这个语句student *stu;
stu = new student[12];动态分配数组对象是要指定大小,其次这是已经产生了12个对象指针,他调用了12次构造函数,这不是野指针,他有自己的地址,他也不会造成非法访问;
stu = new student[12];动态分配数组对象是要指定大小,其次这是已经产生了12个对象指针,他调用了12次构造函数,这不是野指针,他有自己的地址,他也不会造成非法访问;
#12
楼上,你讲的只是其中一种情况,还有一种情况不调用构造函数。
所以,这样:
所以,这样:
student* stu = (student*)malloc (12*sizeof(student));
for(int i = 0; i < 12; i++)new(&stu[i])student;
#13
楼上的楼上讲的很好。
#14
只是楼主这种情况下,构造函数是必定调用。
如果遇到下面的情况,构造函数是不被调用的:
如果遇到下面的情况,构造函数是不被调用的:
class{
public:
string a;
float b;
};
#15
new数组只能调用默认构造函数
#16
你还没明白我的意思。如果我执行student *stu; stu = new student[];就如六楼所说:
《因为你只是声明了*stu,并没有初始化它,初始化一个类的对象只能通过调用构造函数,stu本身是个指针,我们没有给指针提供的默认构造函数和自写的构造函数,这样你只是返回申请的指针的地址,但它指向不明,是个野指针,会返回垃圾数据,所以会输出-33606819》
我也知道,既然student *stu; stu = new student[2];可以执行,那就一定是构造函数对他初始化了。
我不明白的是为什么赋初值的情况下对象数组就有了自己的地址,尽管我知道这是一个事实。
#17
2楼的说得很好。构造函数给变量初始化为他分配内存,而new也是为变量分配内存的,
两者的本质和关系实在是理不清,一团麻似的。还请各位指教。
#18
关键是当我们使用关键字new在堆上动态创建一个对象时,它实际上做了三件事: 获得一块内存空间、调用构造函数、返回正确的指针。当然,如果我们创建的是简单类型的变量,那么第二步会被省略。
例如:
class A
{
int i;
public:
A(int _i) :i(_i*_i) {}
void Say() { printf("i=%d\n", i); }
};
//调用new:
A* pa = new A(3);
那么上述动态创建一个对象的过程大致相当于以下三句话(只是大致上):
A* pa = (A*)malloc(sizeof(A));
pa->A::A(3);
return pa;
原因在于new至少有三中含义: new operator、operator new、placement new
#19
谁说构造函数是分配内存的?
#20
这个类也有默认构造函数,只是构造函数的初始化列表和函数体为空。
#21
补充一个错误:
内存泄露。。。
new分配后要delete
内存泄露。。。
new分配后要delete
#22
[code=C/C++]
#include <iostream>
using namespace std;
//类声明:
class student
{
private:
int num;
public:
student();
~student();
int getnum();
};
//成员函数实现:
student::student()
{
num = 100;
}
int student::getnum()
{
return num;
}
student::~student(){}
//主函数:
int main()
{
student *stu;
stu = new student;
cout << stu->getnum() <<endl;
return 0;
}[code=C/C++]
#include <iostream>
using namespace std;
//类声明:
class student
{
private:
int num;
public:
student();
~student();
int getnum();
};
//成员函数实现:
student::student()
{
num = 100;
}
int student::getnum()
{
return num;
}
student::~student(){}
//主函数:
int main()
{
student *stu;
stu = new student;
cout << stu->getnum() <<endl;
return 0;
}[code=C/C++]
#23
多谢各位了。终于可以结贴了。