new只是申请了一段内存空间,却没有调用构造函数初始化对象。下面的情况怎样才能调用构造函数呢?

时间:2021-09-23 19:47:52
#include<iostream>
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; 

改成这样就行了

#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并未初始化;


#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;,呵呵

#7


多谢了,确实这个地方粗心了。

#8


虽然经常来csdn,但是提问题还是第一次。想不到有这么多热心的朋友帮忙,非常感谢。
kxiaopeng 兄弟还给我逐行耐心解释,多谢。

#9


刚才按照lzr4304061988012的做法,把对象数组的元素个数赋值stu = new student[2]也可以输出100了。
我就很奇怪,因为我原来是用while循环动态创建对象数组,相当于每循环一次创建一个对象,但运行不了。而这样赋值以后就可以运行了。为什么对象数组元素个数赋初值以后(赋值为1也可以),构造函数就可以将每个对象初始化了?这样就不是野指针了,不明白。

{这次还有一个收获,就是第一次这样用指针 stu->student::student(); cout << stu->getnum() << endl;
我把函数里面的int去掉以后,这一句也可以输出100}

#10


你对构造函数不够了解,基础太差了!你要知道对象的生灭,构造函数是用来创建对象的,既然对象已经创建那么构造函数肯定被执行了,也就是先调用构造函数才能创建对象的;只要你执行了这个语句student *stu; 
stu = new student[12];动态分配数组对象是要指定大小,其次这是已经产生了12个对象指针,他调用了12次构造函数,这不是野指针,他有自己的地址,他也不会造成非法访问; 

#11


你对构造函数不够了解,基础太差了!你要知道对象的生灭,构造函数是用来创建对象的,既然对象已经创建那么构造函数肯定被执行了,也就是先调用构造函数才能创建对象的;只要你执行了这个语句student *stu; 
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


引用 11 楼 ymntomyimi8855 的回复:
你对构造函数不够了解,基础太差了!你要知道对象的生灭,构造函数是用来创建对象的,既然对象已经创建那么构造函数肯定被执行了,也就是先调用构造函数才能创建对象的;只要你执行了这个语句student *stu; 
stu = new student[12];动态分配数组对象是要指定大小,其次这是已经产生了12个对象指针,他调用了12次构造函数,这不是野指针,他有自己的地址,他也不会造成非法访问; 


你还没明白我的意思。如果我执行student *stu; stu = new student[];就如六楼所说:
《因为你只是声明了*stu,并没有初始化它,初始化一个类的对象只能通过调用构造函数,stu本身是个指针,我们没有给指针提供的默认构造函数和自写的构造函数,这样你只是返回申请的指针的地址,但它指向不明,是个野指针,会返回垃圾数据,所以会输出-33606819》 
我也知道,既然student *stu; stu = new student[2];可以执行,那就一定是构造函数对他初始化了。
我不明白的是为什么赋初值的情况下对象数组就有了自己的地址,尽管我知道这是一个事实。

#17


引用 2 楼 richbirdandy 的回复:
怎么可能没有调用构造函数呢 除非遇到异常 
new操作符有两个动作 
1 调用operator new函数 
2 调用相关的构造函数 
遇到异常会回滚

2楼的说得很好。构造函数给变量初始化为他分配内存,而new也是为变量分配内存的,
两者的本质和关系实在是理不清,一团麻似的。还请各位指教。

#18


引用 12 楼 yshuise 的回复:
楼上,你讲的只是其中一种情况,还有一种情况不调用构造函数。 
所以,这样: 

C/C++ codestudent* stu = (student*)malloc (12*sizeof(student));
for(int i = 0; i < 12; i++)new(&stu[i])student;

关键是当我们使用关键字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


引用 14 楼 yshuise 的回复:
只是楼主这种情况下,构造函数是必定调用。 
如果遇到下面的情况,构造函数是不被调用的: 

C/C++ codeclass{
public:
string a;
float  b;
};
这个类也有默认构造函数,只是构造函数的初始化列表和函数体为空。

#21


补充一个错误:
内存泄露。。。
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++]

#23


多谢各位了。终于可以结贴了。

#1


构造函数里面的变量num不是student类的成员变量,局部变量屏蔽掉了成员变量
student::student() 

num = 100; 

改成这样就行了

#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并未初始化;


#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;,呵呵

#7


多谢了,确实这个地方粗心了。

#8


虽然经常来csdn,但是提问题还是第一次。想不到有这么多热心的朋友帮忙,非常感谢。
kxiaopeng 兄弟还给我逐行耐心解释,多谢。

#9


刚才按照lzr4304061988012的做法,把对象数组的元素个数赋值stu = new student[2]也可以输出100了。
我就很奇怪,因为我原来是用while循环动态创建对象数组,相当于每循环一次创建一个对象,但运行不了。而这样赋值以后就可以运行了。为什么对象数组元素个数赋初值以后(赋值为1也可以),构造函数就可以将每个对象初始化了?这样就不是野指针了,不明白。

{这次还有一个收获,就是第一次这样用指针 stu->student::student(); cout << stu->getnum() << endl;
我把函数里面的int去掉以后,这一句也可以输出100}

#10


你对构造函数不够了解,基础太差了!你要知道对象的生灭,构造函数是用来创建对象的,既然对象已经创建那么构造函数肯定被执行了,也就是先调用构造函数才能创建对象的;只要你执行了这个语句student *stu; 
stu = new student[12];动态分配数组对象是要指定大小,其次这是已经产生了12个对象指针,他调用了12次构造函数,这不是野指针,他有自己的地址,他也不会造成非法访问; 

#11


你对构造函数不够了解,基础太差了!你要知道对象的生灭,构造函数是用来创建对象的,既然对象已经创建那么构造函数肯定被执行了,也就是先调用构造函数才能创建对象的;只要你执行了这个语句student *stu; 
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


引用 11 楼 ymntomyimi8855 的回复:
你对构造函数不够了解,基础太差了!你要知道对象的生灭,构造函数是用来创建对象的,既然对象已经创建那么构造函数肯定被执行了,也就是先调用构造函数才能创建对象的;只要你执行了这个语句student *stu; 
stu = new student[12];动态分配数组对象是要指定大小,其次这是已经产生了12个对象指针,他调用了12次构造函数,这不是野指针,他有自己的地址,他也不会造成非法访问; 


你还没明白我的意思。如果我执行student *stu; stu = new student[];就如六楼所说:
《因为你只是声明了*stu,并没有初始化它,初始化一个类的对象只能通过调用构造函数,stu本身是个指针,我们没有给指针提供的默认构造函数和自写的构造函数,这样你只是返回申请的指针的地址,但它指向不明,是个野指针,会返回垃圾数据,所以会输出-33606819》 
我也知道,既然student *stu; stu = new student[2];可以执行,那就一定是构造函数对他初始化了。
我不明白的是为什么赋初值的情况下对象数组就有了自己的地址,尽管我知道这是一个事实。

#17


引用 2 楼 richbirdandy 的回复:
怎么可能没有调用构造函数呢 除非遇到异常 
new操作符有两个动作 
1 调用operator new函数 
2 调用相关的构造函数 
遇到异常会回滚

2楼的说得很好。构造函数给变量初始化为他分配内存,而new也是为变量分配内存的,
两者的本质和关系实在是理不清,一团麻似的。还请各位指教。

#18


引用 12 楼 yshuise 的回复:
楼上,你讲的只是其中一种情况,还有一种情况不调用构造函数。 
所以,这样: 

C/C++ codestudent* stu = (student*)malloc (12*sizeof(student));
for(int i = 0; i < 12; i++)new(&stu[i])student;

关键是当我们使用关键字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


引用 14 楼 yshuise 的回复:
只是楼主这种情况下,构造函数是必定调用。 
如果遇到下面的情况,构造函数是不被调用的: 

C/C++ codeclass{
public:
string a;
float  b;
};
这个类也有默认构造函数,只是构造函数的初始化列表和函数体为空。

#21


补充一个错误:
内存泄露。。。
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++]

#23


多谢各位了。终于可以结贴了。