C++类的小问题

时间:2021-12-11 19:31:32
#include <iostream>
using namespace std;
class  CLS
{
public:
int m_i;
CLS(int i):m_i(i){}
CLS()
{
CLS(0);
}
};
int main()
{

CLS obj;
cout << obj.m_i << endl;
return 0;
}
输出为随机值,为什么CLS()没有能够正确调用CLS(0)呢?
              类的成员变量为什么不能在声明时初始化?(except for const static integral)

15 个解决方案

#1


CLS构造函数里面的CLS(0);是生成的另一个对象了,不是本对象。所以obj.m_i 不是0.

#2


默认构造函数改为:
CLS()
{
  m_i = 0;

#3


CLS() 

CLS(0); //这里相当于生成了一个临时的对象,当离开CLS()构造函数后,临时对象被析构了,可以用这种方式调用类的其它构造函数:
 new (this)CLS(0);
}

#4


楼主这种写法实际是用一个构造函数调用另一个构造函数时,这时将产生一个CLS类型的临时对象,然后又马上被销毁。

可以进行如下实验:

#include <iostream> 
using namespace std; 
class  CLS 

public: 
int m_i; 
CLS(int i)
{
m_i=i;
cout<<"CLS(int)"<<endl;

CLS() 

CLS(0); 
cout<<"CLS()"<<endl;

~CLS()
{
cout<<"~CLS()"<<endl;
}
}; 
int main() 

CLS obj; 
cout << obj.m_i << endl; 
return 0; 



可以看到,输出为:

CLS(int)
~CLS()
CLS()
-858993460
~CLS()

也就是说,在CLS()调用CLS(0)时,创建了一个临时对象。然后又马上销毁。而你要的CLS对象并没有被赋初始值。

正确的方法是:

class  CLS
{
public:
    int m_i;
    CLS( int i ) : m_i(i){}
    CLS()
    {
        new (this)CLS(0);
    }
};

#5


CLS() 

CLS(0); 
}
===========
构造函数是创造对象的意思。当在一个构造函数调用另外一个构造函数,是创造另外
一个对象的,也就是临时对象。而不是传统的传递函数参数。

另外楼上用定位new是不行的。

#6


CLS()
{
生成了别的对象了。。。
CLS(0);


因为构造函数和别的成员函数不太一样。如果你这样调用就会产生一个临时的变量。
所以你这里不能为了节省代码 不写出来。
乖乖的写吧

#7


产生的是临时对象。楼主不妨在构造函数上添加默认参数CLS(int i=0)

#8


引用 4 楼 forsiny 的回复:
楼主这种写法实际是用一个构造函数调用另一个构造函数时,这时将产生一个CLS类型的临时对象,然后又马上被销毁。

可以进行如下实验:
C/C++ code
#include<iostream>usingnamespace std;class  CLS 
{public:int m_i; 
    CLS(int i)
    {
        m_i=i;
        cout<<"CLS(int)"<<endl;
    } 
    CLS() 
    { 
        CLS(0); 
        cout<<"CLS()"<<endl;
    }~CLS()
    {
        cout<<"~CLS()"<<endl;
    }
};int main() 

    CLS obj; 
    cout<< obj.m_i<< endl;return0; 
}

可以看到,输出为:

CLS(int)
~CLS()
CLS()
-858993460
~CLS()

也就是说,在CLS()调用CLS(0)时,创建了一个临时对象。然后又马上销毁。而你要的CLS对象并没有被赋初始值。

正确的方法是:
C/C++ codeclass  CLS
{public:int m_i;
    CLS(int i ) : m_i(i){}
    CLS()
    {new (this)CLS(0);
    }
};


new (this)CLS(0);这句大致机理是什么,new是产生新对象,(this)是什么意思,强制转化吗,为什么不会产生新对象了呢?

#9



使用new (this)CLS(0)的思想就是让第二个构造函数在第一次分配好的内存上执行,而不是分配新的内存。这样就可以给你要的对象赋值。

#10


这种new和普通的new不大一样,叫做placement new.

普通的new,比如new CLS()的过程是分配内存->调用构造函数生成对象->返回指针
如果想在分配好的内存上创建一个对象的话,用普通new是不行的,这时就要用到placement new。

placement new一般格式是new (buf)Class,buf即原来内存的指针,对应这里用的new (this)CLS(0).

#11



#include <iostream>
using namespace std;

class A
{
private:
int ival;
public:
A(int i): ival(i) {}
A() { *this = A(20); }
int getIval() { return ival; }
};

int main()
{
A a1;
A a2(10);
cout<<a1.getIval()<<endl
<<a2.getIval()<<endl;
return 0;
}

#12


引用 10 楼 forsiny 的回复:
这种new和普通的new不大一样,叫做placement new.

 普通的new,比如new CLS()的过程是分配内存->调用构造函数生成对象->返回指针
 如果想在分配好的内存上创建一个对象的话,用普通new是不行的,这时就要用到placement new。

 placement new一般格式是new (buf)Class,buf即原来内存的指针,对应这里用的new (this)CLS(0).

学习了!

#13


不能用定位new

#14


引用 13 楼 yshuise 的回复:
不能用定位new


为什么呢?

#15


引用 14 楼 forsiny 的回复:
引用 13 楼 yshuise 的回复:
 不能用定位new


 为什么呢?

《exceptional c++》或《more exceptional c++》后面的章节有详细的讨论这个定位new以及内存管理的问题。

#1


CLS构造函数里面的CLS(0);是生成的另一个对象了,不是本对象。所以obj.m_i 不是0.

#2


默认构造函数改为:
CLS()
{
  m_i = 0;

#3


CLS() 

CLS(0); //这里相当于生成了一个临时的对象,当离开CLS()构造函数后,临时对象被析构了,可以用这种方式调用类的其它构造函数:
 new (this)CLS(0);
}

#4


楼主这种写法实际是用一个构造函数调用另一个构造函数时,这时将产生一个CLS类型的临时对象,然后又马上被销毁。

可以进行如下实验:

#include <iostream> 
using namespace std; 
class  CLS 

public: 
int m_i; 
CLS(int i)
{
m_i=i;
cout<<"CLS(int)"<<endl;

CLS() 

CLS(0); 
cout<<"CLS()"<<endl;

~CLS()
{
cout<<"~CLS()"<<endl;
}
}; 
int main() 

CLS obj; 
cout << obj.m_i << endl; 
return 0; 



可以看到,输出为:

CLS(int)
~CLS()
CLS()
-858993460
~CLS()

也就是说,在CLS()调用CLS(0)时,创建了一个临时对象。然后又马上销毁。而你要的CLS对象并没有被赋初始值。

正确的方法是:

class  CLS
{
public:
    int m_i;
    CLS( int i ) : m_i(i){}
    CLS()
    {
        new (this)CLS(0);
    }
};

#5


CLS() 

CLS(0); 
}
===========
构造函数是创造对象的意思。当在一个构造函数调用另外一个构造函数,是创造另外
一个对象的,也就是临时对象。而不是传统的传递函数参数。

另外楼上用定位new是不行的。

#6


CLS()
{
生成了别的对象了。。。
CLS(0);


因为构造函数和别的成员函数不太一样。如果你这样调用就会产生一个临时的变量。
所以你这里不能为了节省代码 不写出来。
乖乖的写吧

#7


产生的是临时对象。楼主不妨在构造函数上添加默认参数CLS(int i=0)

#8


引用 4 楼 forsiny 的回复:
楼主这种写法实际是用一个构造函数调用另一个构造函数时,这时将产生一个CLS类型的临时对象,然后又马上被销毁。

可以进行如下实验:
C/C++ code
#include<iostream>usingnamespace std;class  CLS 
{public:int m_i; 
    CLS(int i)
    {
        m_i=i;
        cout<<"CLS(int)"<<endl;
    } 
    CLS() 
    { 
        CLS(0); 
        cout<<"CLS()"<<endl;
    }~CLS()
    {
        cout<<"~CLS()"<<endl;
    }
};int main() 

    CLS obj; 
    cout<< obj.m_i<< endl;return0; 
}

可以看到,输出为:

CLS(int)
~CLS()
CLS()
-858993460
~CLS()

也就是说,在CLS()调用CLS(0)时,创建了一个临时对象。然后又马上销毁。而你要的CLS对象并没有被赋初始值。

正确的方法是:
C/C++ codeclass  CLS
{public:int m_i;
    CLS(int i ) : m_i(i){}
    CLS()
    {new (this)CLS(0);
    }
};


new (this)CLS(0);这句大致机理是什么,new是产生新对象,(this)是什么意思,强制转化吗,为什么不会产生新对象了呢?

#9



使用new (this)CLS(0)的思想就是让第二个构造函数在第一次分配好的内存上执行,而不是分配新的内存。这样就可以给你要的对象赋值。

#10


这种new和普通的new不大一样,叫做placement new.

普通的new,比如new CLS()的过程是分配内存->调用构造函数生成对象->返回指针
如果想在分配好的内存上创建一个对象的话,用普通new是不行的,这时就要用到placement new。

placement new一般格式是new (buf)Class,buf即原来内存的指针,对应这里用的new (this)CLS(0).

#11



#include <iostream>
using namespace std;

class A
{
private:
int ival;
public:
A(int i): ival(i) {}
A() { *this = A(20); }
int getIval() { return ival; }
};

int main()
{
A a1;
A a2(10);
cout<<a1.getIval()<<endl
<<a2.getIval()<<endl;
return 0;
}

#12


引用 10 楼 forsiny 的回复:
这种new和普通的new不大一样,叫做placement new.

 普通的new,比如new CLS()的过程是分配内存->调用构造函数生成对象->返回指针
 如果想在分配好的内存上创建一个对象的话,用普通new是不行的,这时就要用到placement new。

 placement new一般格式是new (buf)Class,buf即原来内存的指针,对应这里用的new (this)CLS(0).

学习了!

#13


不能用定位new

#14


引用 13 楼 yshuise 的回复:
不能用定位new


为什么呢?

#15


引用 14 楼 forsiny 的回复:
引用 13 楼 yshuise 的回复:
 不能用定位new


 为什么呢?

《exceptional c++》或《more exceptional c++》后面的章节有详细的讨论这个定位new以及内存管理的问题。