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;
}
CLS()
{
m_i = 0;
}
#3
CLS()
{
CLS(0); //这里相当于生成了一个临时的对象,当离开CLS()构造函数后,临时对象被析构了,可以用这种方式调用类的其它构造函数:
new (this)CLS(0);
}
{
CLS(0); //这里相当于生成了一个临时的对象,当离开CLS()构造函数后,临时对象被析构了,可以用这种方式调用类的其它构造函数:
new (this)CLS(0);
}
#4
楼主这种写法实际是用一个构造函数调用另一个构造函数时,这时将产生一个CLS类型的临时对象,然后又马上被销毁。
可以进行如下实验:
可以看到,输出为:
CLS(int)
~CLS()
CLS()
-858993460
~CLS()
也就是说,在CLS()调用CLS(0)时,创建了一个临时对象。然后又马上销毁。而你要的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是不行的。
{
CLS(0);
}
===========
构造函数是创造对象的意思。当在一个构造函数调用另外一个构造函数,是创造另外
一个对象的,也就是临时对象。而不是传统的传递函数参数。
另外楼上用定位new是不行的。
#6
CLS()
{
生成了别的对象了。。。
CLS(0);
}
因为构造函数和别的成员函数不太一样。如果你这样调用就会产生一个临时的变量。
所以你这里不能为了节省代码 不写出来。
乖乖的写吧
{
生成了别的对象了。。。
CLS(0);
}
因为构造函数和别的成员函数不太一样。如果你这样调用就会产生一个临时的变量。
所以你这里不能为了节省代码 不写出来。
乖乖的写吧
#7
产生的是临时对象。楼主不妨在构造函数上添加默认参数CLS(int i=0)
#8
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).
普通的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
学习了!
#13
不能用定位new
#14
为什么呢?
#15
《exceptional c++》或《more exceptional c++》后面的章节有详细的讨论这个定位new以及内存管理的问题。
#1
CLS构造函数里面的CLS(0);是生成的另一个对象了,不是本对象。所以obj.m_i 不是0.
#2
默认构造函数改为:
CLS()
{
m_i = 0;
}
CLS()
{
m_i = 0;
}
#3
CLS()
{
CLS(0); //这里相当于生成了一个临时的对象,当离开CLS()构造函数后,临时对象被析构了,可以用这种方式调用类的其它构造函数:
new (this)CLS(0);
}
{
CLS(0); //这里相当于生成了一个临时的对象,当离开CLS()构造函数后,临时对象被析构了,可以用这种方式调用类的其它构造函数:
new (this)CLS(0);
}
#4
楼主这种写法实际是用一个构造函数调用另一个构造函数时,这时将产生一个CLS类型的临时对象,然后又马上被销毁。
可以进行如下实验:
可以看到,输出为:
CLS(int)
~CLS()
CLS()
-858993460
~CLS()
也就是说,在CLS()调用CLS(0)时,创建了一个临时对象。然后又马上销毁。而你要的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是不行的。
{
CLS(0);
}
===========
构造函数是创造对象的意思。当在一个构造函数调用另外一个构造函数,是创造另外
一个对象的,也就是临时对象。而不是传统的传递函数参数。
另外楼上用定位new是不行的。
#6
CLS()
{
生成了别的对象了。。。
CLS(0);
}
因为构造函数和别的成员函数不太一样。如果你这样调用就会产生一个临时的变量。
所以你这里不能为了节省代码 不写出来。
乖乖的写吧
{
生成了别的对象了。。。
CLS(0);
}
因为构造函数和别的成员函数不太一样。如果你这样调用就会产生一个临时的变量。
所以你这里不能为了节省代码 不写出来。
乖乖的写吧
#7
产生的是临时对象。楼主不妨在构造函数上添加默认参数CLS(int i=0)
#8
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).
普通的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
学习了!
#13
不能用定位new
#14
为什么呢?
#15
《exceptional c++》或《more exceptional c++》后面的章节有详细的讨论这个定位new以及内存管理的问题。