c++构造函数用new用法_c++中对类使用new和构造函数 - CSDN
  • 算法和数据结构就是编程的一个重要部分,你若失掉了算法和数据结构,你就把一切都失掉了。... 使用new运算符在堆中创建一个对戏那个时,也会自动调用构造函数来实例化该对象的数据成员。 /*使

          算法和数据结构就是编程的一个重要部分,你若失掉了算法和数据结构,你就把一切都失掉了。


           系统会自动在栈中为每个变量开辟内存空间,以保证数值被合理地存放。

           由于栈是系统自动分配的,因此速度较快,但是缺点是可存放的空间小,2M。


          使用new运算符在堆中创建一个对戏那个时,也会自动调用构造函数来实例化该对象的数据成员。



    /*使用NEW运算符在堆中开辟一块新空间,例程如下:
    #include <iostream>
    using std::cout;
    class A
    {
    public:
    A(){cout<<"构造函数执行完毕\n";};
    };
    int main()
    {
    A *p;     //声明一个属于A类的指针p
    p=new A; //使用new运算符创建一块堆中空间,它的大小由类A的数据成员的类型和数量
    //来定,由于堆在内存中都是匿名的,因此这里没有为它命名,只是将它的内存
    //地址赋给了指针p


    return 0;
    }
    */


    //使用new运算符创建并实例化一个对象,例程如下:
    #include <iostream>
    using std::cout;
    class A
    {
    public:
    A(int a,int b){i=a;j=b;cout<<"构造函数执行完毕\n";};
    void print(){cout<<i*j<<"\n";}
    void set(int a,int b){i=a;j=b;}
    private:
    int i,j;
    };
    int main()
    {
    A *p=new A(1,2); //在创建一个对象的同时实例化它的数据成员
    p->print();   //输出结果
    p->set(7,8);   //利用成员函数访问该对象的数据成员并赋值
    p->print();   //输出结果
    return 0;
    }    



    使用new运算符建立一个类的对象时,比如说类A的对象,new首先分配足以保证该类的一个对象所需要的内存,然后自动调用

    构造函数来初始化这块内存,再返回这个对象的地址。



    展开全文
  • C++构造函数简单用法

    2018-05-12 18:01:40
    1.构造函数1.1 基本概念:每个类都有构造函数,如果自己不写,编译器会生成一个默认的无参数构造函数构造函数名字与类名相同,可以有参数,不可以有返回值(void也不可以)。构造函数的作用是对对象进行初始化,如...

    个人笔记,仅供复习

    1.构造函数

    1.1 基本概念:

    • 每个类都有构造函数,如果自己不写,编译器会生成一个默认的无参数构造函数。
    • 构造函数名字与类名相同,可以有参数,不可以有返回值(void也不可以)。
    • 构造函数的作用是对对象进行初始化,如给变量赋初值。

    1.2 注意:

    • 如果定义了构造函数,则编译器不生成默认的无参数构造函数。
    • 对象生成时构造函数自动被调用。对象一旦生成,就再也不能在其上执行构造函数。
    • 一个类可以有多个构造函数(函数重载)。
    • 对象生成调用的可能是构造函数或复制构造函数。

    1.3 构造函数的意义:

            构造函数执行必要的初始化工作,有了构造函数就不必再写初始化函数,也不用担心对象没有初始化。

    1.4 代码实例:

    #include<iostream>
    #include<string>
    using namespace std;
    class Myclass{
    	private :
    		int int_a;
    		string str;
    	public :
    		Myclass(int x = 0,string y = "123"){
    			int_a = x;
    			str = y;
    		}
    		void print(){
    			cout << int_a << " " << str << endl;
    		}
    };
    int main()
    {
    	Myclass mc(1,"456");
    	mc.print();
    	return 0;
    }

    1.5 可以有多个构造函数,参数个数或类型不同(函数重载):

        1.5.1 冒号语法在构造函数中用法:  用在构造函数后表示:初始化列表 

         构造函数初始化时必须采用初始化列表一共有三种情况: 

    1. 需要初始化的数据成员是成员对象
    2. 需要初始化const 修饰的类成员
    3. 需要初始化引用成员数据
    #include<iostream>
    #include<string>
    using namespace std;
    class Myclass{
    	private :
    		int int_a;
    		string str;
    	public :
    		Myclass(int x,string y):int_a(x),str(y) {}//1
    		Myclass(int x):int_a(x) {}//2
    		Myclass(string y):str(y) {}//3
    		void print(){
    			cout << int_a << " " << str << endl;
    		}
    };
    int main()
    {
    	Myclass mc(1,"456");//调用1
    	Myclass mc2(5);//调用2 
    	Myclass mc3("abc");//调用3 
    	return 0;
    }

    1.6 构造函数参数可以是类本身:

    #include<iostream>
    #include<string>
    using namespace std;
    class Complex {
    	private :
    		double real, imag;
    	public:
    		Complex(double r, double i );
    		Complex (double r );
    		Complex (Complex c1, Complex c2);
    };
    Complex::Complex(double r, double i) {
    real = r; imag = i;
    }
    
    Complex::Complex(double r){
    	real = r; imag = 0;
    }
    Complex::Complex (Complex c1, Complex c2){
    	real = c1.real+c2.real;
    	imag = c1.imag+c2.imag;
    }
    
    int main()
    {
    	Complex c1(3) , c2 (1,0), c3(c1,c2);// c1 = {3, 0}, c2 = {1, 0}, c3 = {4, 0};
    	return 0;
    }

    1.7 构造函数在数组中的使用:

            每生成一个类,就调用一次构造函数。生成数组类的时候,可以用 { } 对对应的类调用构造函数。

    #include<iostream>
    using namespace std;
    class Test {
    	public:
    		Test( int n) { } //(1)
    		Test( int n, int m) { } //(2)
    		Test() { } //(3)
    };
    int main()
    {
    	Test array1[3] = { 1, Test(1,2) };
    	// 三个元素分别用(1),(2),(3)初始化
    	Test array2[3] = { Test(2,3), Test(1,2) , 1};
    	// 三个元素分别用(2),(2),(1)初始化
    	Test * pArray[3] = { new Test(4), new Test(1,2) };
    	//两个元素分别用(1),(2) 初始化
    	return 0;
    } 
    

    2.复制构造函数

    2.1 基本概念:

    • 只有一个参数,即对同类对象的引用
    • 形如X::X( X& )X::X( const X &),二者选一,后者能以常量对象作为参数
    • 如果没有定义复制构造函数,那么编译器生成默认复制构造函数。默认的复制构造函数完成复制功能

    注:

    • 不允许有形如 X::X( X )的构造函数
    • 如果定义了自己的复制构造函数,那默认复制构造函数将不存在

    2.2 复制构造函数起作用的三种情况:

    • 用一个对象去初始化同类的另一个对象
    	Complex c2(c1);
    	Complex c2 = c1;//初始化语句,非赋值语句。 
    • 如果某函数有一个参数是类A的对象,那么该函数被调用时,类A的复制构造函数将被调用
    #include<iostream>
    #include<string>
    using namespace std;
    class A
    {
    	public:
    		A() { };
    		A( A & a) {
    			cout << "Copy constructor called" <<endl;
    		}
    };
    void Func(A a1){ }
    int main(){
    	A a2;
    	Func(a2);
    	return 0;
    }
    程序输出结果为: Copy constructor called

    • 如果函数的返回值是类A的对象时,则函数返回时,A的复制构造函数被调用
    #include<iostream>
    #include<string>
    using namespace std;
    class A
    {
    	 public:
    		 int v;
    		 A(int n) { v = n; };
    		 A( const A & a) {
    			 v = a.v;
    			 cout << "Copy constructor called" <<endl;
    		 }
    };
    A Func() {
    	A b(4);
    	return b;
    }
    int main() {
    	cout << Func().v << endl; 
    	return 0;
    }

    输出结果:Copy constructor called

                        4

    有些编译器会对上述代码进行优化(如dev),那么就只会输出4。

    注:对象之间赋值并不导致复制构造函数被调用

    2.3 常量引用参数的使用:

    void Fun(Myclass obj_){
    	cout << "fun" <<endl;
    }
    这样的函数,调用时生成形参会引发复制构造函数开销比较大可以使用Myclass & 引用类型作为形参。如果希望实参的值不会被改变,可以加上const关键字。

    3.析构函数

    3.1 什么是析构函数:名字与类名相同,在前面加‘~’,没有参数和返回值,一个类最多只能有一个析构函数。

    3.2 特点:

    • 名字与类名相同,在前面加‘~’, 没有参数和返回值,一 个类最多只能有一个析构函数。 
    • 析构函数对象消亡时即自动被调用。可以定义析构函数来在对象消亡前做善后工作,比如释放分配的空间等。 
    • 如果定义类时没写析构函数,则编译器生成缺省析构函数。 缺省析构函数什么也不做。 
    • 如果定义了析构函数,则编译器不生成缺省析构函数。 

    3.3 代码实例:

    #include<iostream>
    using namespace std;
    class A
    {
    	 public:
    		 ~A(){
    		 	cout << "now" <<endl;
    		 } 
    };
    void Fun(){
    	A a;
    }
    int main() {
    	Fun();
    	return 0;
    }

    当函数调用结束时,局部对象a被释放,析构函数被调用。每当一个对象消亡,就必定会调用析构函数。

    3.4 析构函数和数组:对象数组生命期结束时,对象数组的每个元素的析构函数都会被调用。

    3.5 析构函数和delete运算符:

    • delete导致析构函数被调用
    • 若new一个对象数组,那么用delete释放时应写[]。否则只delete一个对象(调用一次析构函数)
    Ctest  * pTest;
    pTest = new Ctest;  //构造函数调用 
    delete pTest;          //析构函数调用 
    pTest = new Ctest[3]; //构造函数调用3次 
    delete [] pTest;           //析构函数调用3次 

    4.类型转换构造函数

    4.1 基本概念:

    • 定义转换构造函数的目的是实现类型的自动转换
    • 只有一个参数,而且不是复制构造函数的构造函数,一般就可以看作是类型转换构造函数
    • 当需要的时候,编译系统会自动调用类型转换构造函数,建立一个无名的临时对象(或临时变量)

    4.2 代码实例:

    #include<iostream>
    using namespace std;
    class A{
    	public:
    		int first;
    		double second;
    		A(int a){
    			this->first = a;
    			this->second = 0.5;
    		}
    };
    int main()
    {
    	A a = 4;//调用了类型转换构造函数 
    	a = 5;//调用了类型转换构造函数 
    	cout << a.first << " " << a.second << endl;
    	return 0;
    }

    展开全文
  • C++:在构造函数使用new时应该注意的事项标签(空格分隔): c++ 如果在构造函数使用new初始化指针对象,那么应该在析构函数中使用delete释放对象。 new和delete必须相互兼容,new对应于delete,new[]对应于...

    C++:在构造函数中使用new时应该注意的事项

    标签(空格分隔): c++


    • 如果在构造函数中使用了new初始化指针对象,那么应该在析构函数中使用delete释放对象。
    • new和delete必须相互兼容,new对应于delete,new[]对应于delete[]。
    • 如果有多个构造函数,则必须以相同的方式使用new。然而,可以在一个构造函数中使用new初始化指针,而在另一个构造函数中将其初始化为空(0、NULL、nullptr),因为delete可以用于空指针。
    • 应该定义一个复制构造函数,通过深度复制将一个对象初始化为另一个对象。具体地说,复制构造函数应该分配足够的内存空间来复制数据,而不仅仅是数据的地址。另外还应该更新所有受影响的静态成员。
    • 应当定义一个赋值运算符,通过深度复制将一个对象复制给另一个对象。具体地说,该方法应该完成这样的操作:检查自我赋值情况,释放成员指针以前指向的内存(赋值运算符可以在类的生命周期任何时刻被调用,不仅仅是初始化),复制数据而不仅仅是数据的地址。
    展开全文
  • c++的类中,构造函数是一种特殊的成员函数,在每次创建创建一个类的时候会默认调用构造函数进行初始化工作。 构造函数用来完成一些必要的初始化工作,有了构造函数之后,就无需再单独写初始化函数,并且也不必担心...

    构造函数

    引入

    在c++的类中,构造函数是一种特殊的成员函数,在每次创建创建一个类的时候会默认调用构造函数进行初始化工作。

    构造函数用来完成一些必要的初始化工作,有了构造函数之后,就无需再单独写初始化函数,并且也不必担心忘记调用初始化函数。

    基本概念

    构造函数具有如下几个特点

    • 名字与类名相同,可以有参数,但是不能有返回值(void也不行)
    • 作用是对对象进行初始化工作,如给成员变量赋值等。
    • 如果定义类时没有写构造函数,系统会生成一个默认的无参构造函数,默认构造函数没有参数,不做任何工作。
    • 如果定义了构造函数,系统不再生成默认的无参构造函数
    • 对象生成时构造函数自动调用,对象一旦生成,不能在其上再次执行构造函数
    • 一个类可以有多个构造函数,为重载关系

    构造函数

    默认无参构造函数

    下面来看一个简单的例子。

    class Complex {//复数类
    private:
    	double real, imag;//分别表示实部以及虚部
    public:
    	void set(double r, double i) {
    		real = r;
    		imag = i;
    	}
    };
    

    对于上面的复数类,real表示实部,imag表示虚部,set(set(double r, double i))函数为初始化函数,我们并没有为其编写构造函数,此时编译系统将生成一个默认的无参构造函数。

    假设有如下调用:

    int main() {
    	Complex c1;//默认构造函数被调用
    	Complex* c2 = new Complex;//默认构造函数被调用
    	return 0;
    }
    

    在对象生成的时候,编译系统自动调用默认的无参构造函数对其进行初始化工作(什么都没做),此时我们必须自己调用set(double r, double i)函数才能对其进行初始化操作。

    编写构造函数

    接下来我们为上面的类编写一个构造函数

    class Complex {//复数类
    private:
    	double real, imag;//分别表示实部以及虚部
    public:
    	Complex(double r, double i = 0) {
    		real = r;
    		imag = i;
    	}
    };
    
    int main() {
    	Complex c1;//错误,参数不匹配
    	Complex* c2 = new Complex;//错误,参数不匹配
    	return 0;
    }
    

    当我们在调用上面的代码生成对象c1c2时,编译系统会给我们报错。原因是我们编写的构造函数需要接收至少一个参数,而我们在初始化的时候没有给出任何的参数。

    对上面的代码进行如下的改动:

    int main() {
    	Complex c1(1);//OK
    	Complex* c2 = new Complex(2,5);//OK
    	return 0;
    }
    

    此时c1c2就可以正常地生成。

    • 对于c1对象,用1来初始化实部,用缺省的0初始化虚部。
    • 对于c2对象,用2来初始化实部,用5初始化虚部。

    构造函数重载

    对于同一个类,可以有多个构造函数,只要参数个数或类型不同就可,他们之间为重载的关系。

    class Complex {//复数类
    private:
    	double real, imag;//分别表示实部以及虚部
    public:
    	//构造函数
    	Complex();
    	Complex(double r);
    	Complex(double r, double i);
    	Complex(Complex c1, Complex c2);
    };
    Complex::Complex() {
    	real = 0;
    	imag = 0;
    }
    Complex::Complex(double r) {
    	real = r;
    	imag = 0;
    }
    Complex::Complex(double r, double i) {
    	real = r;
    	imag = i;
    }
    Complex::Complex(Complex c1, Complex c2) {
    	real = c1.real + c2.real;
    	imag = c1.imag + c2.imag;
    }
    

    在上面的类中,分别写了四个构造函数

    • Complex()无参构造函数,realimag都初始化为0
    • Complex(double r)real初始化为rimag初始化为0
    • Complex(double r, double i)real初始化为rimag初始化为i
    • Complex(Complex c1, Complex c2)real初始化为c1.real + c2.realimag初始化为c1.imag + c2.imag

    对于上面的类,假设我们有如下调用:

    int main() {
    	Complex c1;//调用Complex()构造函数
    	Complex c2(2);//调用Complex(double r)构造函数
    	Complex c3(2, 3);//调用Complex(double r, double i)构造函数
    	Complex c4(c1, c2);//Complex(Complex c1, Complex c2)构造函数
    	return 0;
    }
    
    • 对于c1对象,调用Complex()无参构造函数,将realimag都初始化为0
    • 对于c2对象,调用Complex(double r)构造函数,将real初始化为2imag初始化为0
    • 对于c3对象,调用Complex(double r, double i)构造函数,将real初始化为2imag初始化为3
    • 对于c4对象,调用Complex(Complex c1, Complex c2)real初始化为c1.real + c2.real=2imag初始化为c1.imag + c2.imag=0

    构造函数在数组中的使用

    下面我们通过一个实例来查看对与对象数组是如何调用构造函数进行初始化的。

    class Complex {//复数类
    private:
    	double real, imag;//分别表示实部以及虚部
    public:
    	//构造函数
    	Complex() {
    		cout << "无参构造函数初始化" << endl;
    	}
    	Complex(double r) {
    		cout << "一个参数的构造函数初始化" << endl;
    	}
    	Complex(double r, double i) {
    		cout << "两个参数的构造函数初始化" << endl;
    	}
    };
    

    我们为上面的类写了三个构造函数,在调用无参构造函数时输出无参构造函数初始化,调用一个参数的构造函数时输出一个参数的构造函数初始化,调用两个构造函数初始化时输出两个参数的构造函数初始化

    假设我们有如下的对象生成:

    int main() {
    	cout << "array1" << endl;
    	Complex array1[3];
    
    	cout << "array2" << endl;
    	Complex array2[3] = { 1,2 };
    
    	cout << "array3" << endl;
    	Complex array3[3] = { 1,Complex(1,2) };
    
    	cout << "array4" << endl;
    	Complex* array4 = new Complex[3];
        
    	cout << "array5" << endl;
    	Complex* array5[3] = { new Complex(1),new Complex(2,3) };
        
    	delete[]array4;
    	return 0;
    }
    
    • 对于array1生成的三个对象,我们没有为其指定参数,所以都调用无参构造函数进行初始化。
    • 对于array2生成的三个对象,我们指定了前两个的参数表为12,所以调用一个参数的构造函数进行初始化,第三个对象没有指定参数,所以调用无参构造函数进行初始。
    • 对于array3生成的三个对象,第一个对象参数为1,所以调用无参构造函数初始化,第二个对象参数为(1,2),所以调用两个参数的构造函数初始化,对于第三个对象,我们没有指定参数,所以调用无参构造函数初始化。
    • array4为一个Complex类的指针,通过new运算符动态分配三个对象,并将其首地址返回给array4,在此我们并没有为new出来的三个对象指定初始化参数,所以三个对象都调用无参构造函数初始化。
    • array5为一个Complex类的指针数组,包含三个指针对象。第一个new Complex(1)生成了一个对象,且参数为1,所以调用一个参数的构造函数;第二个元素通过new Complex(2,3)生成一个对象,且参数为(2,3),所以调用两个参数的构造函数;第三个我们没有为其动态分配内存空间,所以不会导致对象的生成,仅存在一个对象指针。所以**array5仅生成了两个对象**。

    对于上面的程序,我们可以得到如下的运行结果:

    array1
    无参构造函数初始化
    无参构造函数初始化
    无参构造函数初始化
    array2
    一个参数的构造函数初始化
    一个参数的构造函数初始化
    无参构造函数初始化
    array3
    一个参数的构造函数初始化
    两个参数的构造函数初始化
    无参构造函数初始化
    array4
    无参构造函数初始化
    无参构造函数初始化
    无参构造函数初始化
    array5
    一个参数的构造函数初始化
    两个参数的构造函数初始化
    
    展开全文
  • c++ 构造函数详解

    2020-04-06 15:10:52
    c++构造函数详解。(构造函数的分类、拷贝构造函数)
  • C++使用new来初始化对象的指针成员时必须注意如下事项: 1. 如果在构造函数使用...3. 如果存在多个构造函数,则必须以相同的方式使用new,要么都用new,要么都用new [ ],因为只有一个析构函数,因此所有...
  • C++构造函数使用new

    2020-06-18 18:08:24
    如果在构造函数使用new来初始化指针成员,则应在析构函数中使用delete。 new和delete必须相互兼容。new对应delete,new[]对应于delete[]。 如果有多个构造函数,则必须以相同的方式使用new,要么都带中括号,要么...
  • c++类的构造函数详解 一、 构造函数是干什么的 class Counter { public:  // 类Counter的构造函数  // 特点:以类名作为函数名,无返回类型  Counter()  {  ...
  • C++构造函数中转而调用其它构造函数的三种方法 0x00 在初始化列表中调调另一个构造函数 /** * warning: delegating constructors only available with -std=c++11 or -std=gnu++11 */ Teacher::Teacher():...
  • 构造函数 ,是一种特殊的方法 。主要用来在创建对象时初始化对象, 即为对象成员变量赋初始值,总与new运算符一起使用在创建对象的语句中 。特别的一个类可以有多个构造函数 ,可根据其参数个数的不同或参数类型的...
  • 百度百科:构造函数 ,是一种特殊的方法。主要用来在创建对象时初始化对象, 即为对象成员变量赋初始值,总与new运算符一起使用在创建对象的语句中。特别的一个类可以有多个构造函数 ,可根据其参数个数的不同或参数...
  • 在我们调用构造函数时,会使用new操作符 + 构造函数,在这种方式调用构造函数时,会执行以下几个步骤: - 创建一个新对象 - 将构造函数的作用域赋给这个新对象,这时this指针就指向了这个对象 - 执行构造函数...
  • 1、默认构造函数构造函数 (1)构造函数C++用于构建类的新对象时需要调用的函数,该函数无返回类型!(注意:是“无”! 不是空!(void))。 (2)默认构造函数:默认构造函数是在调用时不需要显示地传入实参...
  • C++中一般创建对象,拷贝或赋值的方式有构造函数,拷贝构造函数,赋值函数这三种方法。下面就详细比较下三者之间的区别以及它们的具体实现 1.构造函数 构造函数是一种特殊的类成员函数,是当创建一个类的对象时,...
  • 问题:c++构造函数的知识在各种c++教材上已有介绍,不过初学者往往不太注意观察和总结其中各种构造函数的特点和用法,故在此我根据自己的c++编程经验总结了一下c++中各种构造函数的特点,并附上例子,希望对初学者...
  • 很多情况下要求当前的程序中只有一个object... 当我们在程序中声明一个对象时,编译器为调用构造函数(如果有的话),而这个调用将通常是外部的,也就是说它不属于class对象本身的调用,假如构造函数是私有的,由于在...
  • 1.C++构造函数和析构函数 构造函数: 构造函数在创建类对象时自动执行,通常用于一些数据的初始化工作,构造函数可以重载,有一个默认构造函数。 析构函数: 在释放对象所占内存时自动执行,不能重载,一个类...
  • C++默认构造函数

    2019-02-22 21:05:37
    默认构造函数 默认的构造函数是指为所有参数都提供了默认值的构造函数,通常是指无参的构造函数。比如下面的类Test,它的默认构造函数就是Test()。 class Test { public: Test(){} // default constructor } ...
1 2 3 4 5 ... 20
收藏数 148,343
精华内容 59,337
关键字:

c++构造函数用new用法