我理解下面的代码,据我所知,当我使用new声明一个对象时,它构造一个特定类型的对象并返回指向该对象的指针。但是当我使用new创建一个student对象时,它不会返回指向该对象的指针。此外,当我打电话给新学生(s1)时,“学生(学生*)”被调用,而不是给出错误,例如没有从学生到学生的类型转换*
#include <bits/stdc++.h>
using namespace std;
class student {
public:
int cool;
student(student* s){ // this constructor is taking pointer to s whereas i am calling it by value below
this->cool=s->cool;
}
student(){
this->cool=1;
}
};
void blah(student s){
printf("cool:%d\n",s.cool);
}
int main(){
student s1=new student(); // here new is not returning student*
s1.cool=2;
student s2=new student(s1); // here we are passing s1 which of type student but constructor (student*) is called why ???
blah(s2);
}
以下是输出我没有任何错误:
凉爽:2
答案 0 :(得分:7)
你正在泄露记忆。
这个构造函数:
student(student* s)
用于隐式地满足转换,因为它未标记为explicit
。那么这里发生了什么:
student s1=new student();
您是堆 - 分配新的student
对象吗? new
表达式求值为指针。当编译器查看分配时,它知道分配不起作用,因为s1
是student
,并且您正在为其分配student *
。所以它寻找一种方法来转换它并找到我上面提到的构造函数。
所以你所做的相当于:
student s1 = student(new student());
由于你永远不会delete
指针,所以堆分配会被泄露,但是从你的角度看你的程序正确执行。
如果您将转换构造函数标记为:
explicit student(student* s)
然后编译器不会自动使用此构造函数进行转换,需要显式调用某种类型,而行student s1=new student();
确实会导致编译时错误,同时允许student s1 = student(new student());
工作(但当然它仍会导致内存泄漏。)
答案 1 :(得分:2)
new
正在返回指向student
的指针。当然是!
第一种情况发生的是student s1 = new student()
行正在调用student(student*)
构造函数来构造s1
。
在第二种情况下,行student s2 = new student(s1)
首先调用默认的复制构造函数,然后调用student(student*)
构造函数来构造s2
。
在这两种情况下,都会发生内存泄漏,因为您没有致电delete
来匹配new
。
这种行为是为什么在单个参数构造函数之前使用explicit
是一个非常好的主意,除非你真的想要这种隐式转换(并且,即使你认为你做了,你可能不会)。
答案 2 :(得分:1)
我不知道你在哪里得到new
没有返回指针的奇怪想法。您发布的代码不以任何方式支持该声明。这个初始化
student s1 = new student();
使用student
创建默认构造的 new
对象。然后new
返回的指针将传递给student::student(student *)
构造函数,因为它应该是。
第二次初始化
student s2 = new student(s1);
使用student
创建复制构造的 new
对象。然后new
返回的指针将传递给student::student(student *)
构造函数,因为它应该是。
为什么您认为第二种情况中的“从student
到student *
的无类型转换”错误并不明确。您的student
类具有由编译器声明和定义的隐式复制构造函数。这是student(s1)
初始化中使用的构造函数。此处无需进行任何student
到student *
转换,也无需出错。
在这两种情况下,student::student(student *)
都会被new
返回的指针调用。看来您出于某种原因认为在第一种情况下student::student(student *)
未被调用。但这是一个完全没有根据的信念。它叫做。