有两个问题,麻烦帮忙看看,谢谢

时间:2022-06-01 13:58:35

#include <iostream>
using namespace std;

class Point3D
{
public:
//virtual ~Point3D();
public:
static Point3D origin;
float x,y,z;
};

int main()
{
Point3D temp;
cout<<temp.z<<endl; //这句在运行时会异常

cout<<&Point3D::z<<endl; // &Point3D::z 返回的是offset ,void* ,那么 cout<< void* 输出的也应该是地址啊,为什么全是1?
cout<<&Point3D::y<<endl;
cout<<&Point3D::x<<endl;
cout<<endl;
printf("&Point3D::z = %p\n",&Point3D::z);
printf("&Point3D::y = %p\n",&Point3D::y);
printf("&Point3D::x = %p\n",&Point3D::x);
}

出现异常的朋友们千万别说是没初始化,即使没初始化也要有默认值。而且只要加上默认构造函数就不会有异常了,为什么?

37 个解决方案

#1


没有构造函数,temp就是没定义,没分配内存,当然会出异常

那你可能就会问编译器不是会提供默认的构造函数吗?

下面的是在网上搜到的,没做验证

C++中一个类无任何构造函数,编译器在什么情况下才提供默认构造函数?
在C++中,如果一个类中没有定义任何的构造函数,那么编译器只有在以下三种情况,才会提供默认的构造函数:
1.如果类有虚成员函数或者虚拟继承父类(即有虚拟基类)时;
2.如果类的基类有构造函数(可以是用户定义的构造函数,或编译器提供的默认构造函数);
3.在类中的所有非静态的对象数据成员,它们所属的类中有构造函数(可以是用户定义的构造函数,或编译器提供的默认构造函数)。

#2


我这里没有异常,不知道你为什么要取一个类的共有成员的地址,这样可行吗?

#3


为什么不生成默认构造函数呢?VS2005

#4


一个类定义之后 如果不实例出对象或是其他方式为其内部成员分配内存 则他是不会开辟空间的 静态除外不过静态要事先做初始化
另外加上构造函数 为什么会有变化 原因很简单 他为代码做了必要的初始化工作 分配了空间给类成员

#5


我这没任何异常

#6


引用 4 楼 zwind_fancy 的回复:
一个类定义之后 如果不实例出对象或是其他方式为其内部成员分配内存 则他是不会开辟空间的 静态除外不过静态要事先做初始化 
另外加上构造函数 为什么会有变化 原因很简单 他为代码做了必要的初始化工作 分配了空间给类成员


他为什么不生成默认构造函数呢?

#7


class Point3D
{
public:
    //virtual ~Point3D();
public:
    static Point3D origin;
    float x,y,z;
};

编译器不会为应该由设计者自己提供初值的类成员变量进行初始化,如果设计者没有提供构造函数,如1楼所说的情况下,编译器会提供一个默认构造函数进行一些初始化操作,否则默认构造函数是无意义的;

在这里出现异常有可能是Z没有明确初始化

cout<<&Point3D::z<<endl; 类成员变量求地址只是求变量在对象内存布局中的偏移,

如果要求地址,必须用对象的成员变量

#8


讨论来讨论去,求这个有意义吗? 不知道哪儿有说这个操作是有意义的...

#9


cout<<temp.z<<endl;        //这句在运行时会异常
没有初始化z变量!!

#10


c++的《运算符好像没有重载这种输出吧!!!

#11


vc2005是很强暴的编译器,在debug状态下自动启用“变量没有初始化”的检查并报错。
根据C++标准,在楼主所说场合是不会自动生成默认构造函数的。
认真去重看基础教材C++ Primer吧。

#12


明白了没构造函数,但下面的还不明白:
cout<<&Point3D::z<<endl;    // &Point3D::z 返回的是offset ,void* ,那么 cout<< void* 输出的也应该是地址啊,为什么全是1?

#13


引用 12 楼 unhappyless 的回复:
明白了没构造函数,但下面的还不明白: 
cout < <&Point3D::z < <endl;    // &Point3D::z 返回的是offset ,void* ,那么 cout < < void* 输出的也应该是地址啊,为什么全是1?

&Point3D::z 返回的是offset ,void* 
哪本书告诉你的?扔了那破书。

#14


引用 13 楼 taodm 的回复:
引用 12 楼 unhappyless 的回复:
明白了没构造函数,但下面的还不明白: 
cout < <&Point3D::z < <endl;    // &Point3D::z 返回的是offset ,void* ,那么 cout < < void* 输出的也应该是地址啊,为什么全是1? 
 
&Point3D::z 返回的是offset ,void* 
哪本书告诉你的?扔了那破书。


我也觉得那书说的有问题,那返回的是什么?

#15


返回的就是“指向成员的指针”,找本C++ Primer好好补课去。

#16




这指针有什么用?能比较大小吗?能装换成void* 吗?

C++ Primer 里没有这些内容吧,倒是其他C++ 大师书籍可能有。

#17


C++ Primer上说啥了?

#18


C++ Primer 里就是些 C++ 基本语法

#19


一楼的描述是对的,我已验证过

#20


引用 18 楼 unhappyless 的回复:
C++ Primer 里就是些 C++ 基本语法

那就去看C++标准。看过了C++标准,你对C++ Primer的认识就会完全不同了。

#21


老大,你就告诉我 &Point3D::z  返回的是什么吧。。。

#22


引用 15 楼 taodm 的回复:
返回的就是“指向成员的指针”,找本C++ Primer好好补课去。

重复答案有什么意义?

#23


要你去C++ Primer补课,是让你自己找出“指向成员的指针”是C++新增的一种基本数据类型。
它其它什么都不是,它就是它自己。
它能做的(符合C++标准规定的)操作C++ Primer都讲了。

#24


那这个指针能不能转换?或比较大小?

#25


你这个 列子  是 不是 Inside C++ object modal 上的 ?

#26


引用 24 楼 unhappyless 的回复:
那这个指针能不能转换?或比较大小?

C++ Primer上如果讲了可以那就可以,如果没讲可以那就不可以。
自己认真到书上找答案。

#27


没有发现任何异常,编译运行都成功

#28


引用 27 楼 wjb_yd 的回复:
没有发现任何异常,编译运行都成功


可能编译器不同吧,&Point3D::z 咋比较大小呢?

#29


加上 构造函数 
还有成员变量要初始化

#30


Run-Time Check Failure #3 - The variable 'temp' is being used without being initialized.
-vs2008
没初始化是正解。
至于
&Point3D::z 返回的是offset 这话确实没有错
所以printf返回是正确的
但是<<没有对此进行重载,默认的是只是返回bool
基本上,等价于下面的语句
所以为1
cout << "Point3d::x = " << (bool) &Point3d::x << endl;

为了正确的输出
可以尝试下面的代码
float Point3D::*const pm = &Point3D::x;
cout << "Point3d::x = " << (const void *&) pm << endl;

#31


当然重载<<也是可以的。。。加上就可以了
template<class T, typename M>
ostream & operator <<(ostream &os, M T::*pm)
{
os << (const void *&) pm;

return os;
}

#32


引用 31 楼 happyboxman 的回复:
当然重载 < <也是可以的。。。加上就可以了 
template <class T, typename M> 
ostream & operator < <(ostream &os, M T::*pm) 

os < < (const void *&) pm; 

return os; 


====================================

 (const void *&)  能转吗?

 &Point3d::x  我就没法转成任何类型

#33


学习了

#34


引用 3 楼 unhappyless 的回复:
为什么不生成默认构造函数呢?VS2005

生成了默认构造函数的,不过对于float x,y,z;没帮你"默认构造",这不是VS2005的义务.

建议记住:
   在对象构造函数里,将所有成员初始化, 你的责任!
   在使用前将数组初始化, 你的责任!
   在适当的时机将字串无效部分置零, 你可以活得久些!

对于cout<<&Point3D::z<<endl;    // &Point3D::z 返回的是offset ,void* ,那么 cout<< void* 输出的也应该是地址啊,为什么全是1?
实在费解为什么会这么写:
对于 &Point3D::z 编译器给你解释为 (float Point3D::*) 看清楚了吧(不是 float* Point3D:: .... ), 是成员的偏移量, float 只起了个sizetype作用;
如果你用: 
    printf("%d,%d,%d",&Point3D::x,&Point3D::y,&Point3D::z);
输出为:
    0,4,8 // 明白了吧.

如果你用cout的话,实际cout 把 (&Point3D::x) 当成bool量, 谁叫你搞这么奇异的东西....
    operator<<(_Bool _Val)
所以输出为 "1" 了, 为什么 &Point3D::x printf输出0,count输出1呢,哈哈,注意下_Bool吧,自己研究下去...(俺知道,就不说)叫你写这东西

#35


引用 32 楼 unhappyless 的回复:
引用 31 楼 happyboxman 的回复:
当然重载 < <也是可以的。。。加上就可以了 
template <class T, typename M> 
ostream & operator < <(ostream &os, M T::*pm) 

os < < (const void *&) pm; 

return os; 

 

==================================== 

(const void *&)  能转吗? 

&Point3d::x  我就没法转成任何类型


是 float &Point3d::* x,,,,天书一般的东西,怎么理解都行,转就别想了

#36


引用 34 楼 mybabyanddear 的回复:
如果你用cout的话,实际cout 把 (&Point3D::x) 当成bool量, 谁叫你搞这么奇异的东西.... 
    operator < <(_Bool _Val) 


哪里有说明是当bool ?

#37


引用 36 楼 unhappyless 的回复:
引用 34 楼 mybabyanddear 的回复:
如果你用cout的话,实际cout 把 (&Point3D::x) 当成bool量, 谁叫你搞这么奇异的东西.... 
    operator < <(_Bool _Val) 
 

哪里有说明是当bool ?


这个不用说明,你跟踪一下就清楚了,或者看调用堆栈, 的确被当作 bool处理了,值全为 true

#1


没有构造函数,temp就是没定义,没分配内存,当然会出异常

那你可能就会问编译器不是会提供默认的构造函数吗?

下面的是在网上搜到的,没做验证

C++中一个类无任何构造函数,编译器在什么情况下才提供默认构造函数?
在C++中,如果一个类中没有定义任何的构造函数,那么编译器只有在以下三种情况,才会提供默认的构造函数:
1.如果类有虚成员函数或者虚拟继承父类(即有虚拟基类)时;
2.如果类的基类有构造函数(可以是用户定义的构造函数,或编译器提供的默认构造函数);
3.在类中的所有非静态的对象数据成员,它们所属的类中有构造函数(可以是用户定义的构造函数,或编译器提供的默认构造函数)。

#2


我这里没有异常,不知道你为什么要取一个类的共有成员的地址,这样可行吗?

#3


为什么不生成默认构造函数呢?VS2005

#4


一个类定义之后 如果不实例出对象或是其他方式为其内部成员分配内存 则他是不会开辟空间的 静态除外不过静态要事先做初始化
另外加上构造函数 为什么会有变化 原因很简单 他为代码做了必要的初始化工作 分配了空间给类成员

#5


我这没任何异常

#6


引用 4 楼 zwind_fancy 的回复:
一个类定义之后 如果不实例出对象或是其他方式为其内部成员分配内存 则他是不会开辟空间的 静态除外不过静态要事先做初始化 
另外加上构造函数 为什么会有变化 原因很简单 他为代码做了必要的初始化工作 分配了空间给类成员


他为什么不生成默认构造函数呢?

#7


class Point3D
{
public:
    //virtual ~Point3D();
public:
    static Point3D origin;
    float x,y,z;
};

编译器不会为应该由设计者自己提供初值的类成员变量进行初始化,如果设计者没有提供构造函数,如1楼所说的情况下,编译器会提供一个默认构造函数进行一些初始化操作,否则默认构造函数是无意义的;

在这里出现异常有可能是Z没有明确初始化

cout<<&Point3D::z<<endl; 类成员变量求地址只是求变量在对象内存布局中的偏移,

如果要求地址,必须用对象的成员变量

#8


讨论来讨论去,求这个有意义吗? 不知道哪儿有说这个操作是有意义的...

#9


cout<<temp.z<<endl;        //这句在运行时会异常
没有初始化z变量!!

#10


c++的《运算符好像没有重载这种输出吧!!!

#11


vc2005是很强暴的编译器,在debug状态下自动启用“变量没有初始化”的检查并报错。
根据C++标准,在楼主所说场合是不会自动生成默认构造函数的。
认真去重看基础教材C++ Primer吧。

#12


明白了没构造函数,但下面的还不明白:
cout<<&Point3D::z<<endl;    // &Point3D::z 返回的是offset ,void* ,那么 cout<< void* 输出的也应该是地址啊,为什么全是1?

#13


引用 12 楼 unhappyless 的回复:
明白了没构造函数,但下面的还不明白: 
cout < <&Point3D::z < <endl;    // &Point3D::z 返回的是offset ,void* ,那么 cout < < void* 输出的也应该是地址啊,为什么全是1?

&Point3D::z 返回的是offset ,void* 
哪本书告诉你的?扔了那破书。

#14


引用 13 楼 taodm 的回复:
引用 12 楼 unhappyless 的回复:
明白了没构造函数,但下面的还不明白: 
cout < <&Point3D::z < <endl;    // &Point3D::z 返回的是offset ,void* ,那么 cout < < void* 输出的也应该是地址啊,为什么全是1? 
 
&Point3D::z 返回的是offset ,void* 
哪本书告诉你的?扔了那破书。


我也觉得那书说的有问题,那返回的是什么?

#15


返回的就是“指向成员的指针”,找本C++ Primer好好补课去。

#16




这指针有什么用?能比较大小吗?能装换成void* 吗?

C++ Primer 里没有这些内容吧,倒是其他C++ 大师书籍可能有。

#17


C++ Primer上说啥了?

#18


C++ Primer 里就是些 C++ 基本语法

#19


一楼的描述是对的,我已验证过

#20


引用 18 楼 unhappyless 的回复:
C++ Primer 里就是些 C++ 基本语法

那就去看C++标准。看过了C++标准,你对C++ Primer的认识就会完全不同了。

#21


老大,你就告诉我 &Point3D::z  返回的是什么吧。。。

#22


引用 15 楼 taodm 的回复:
返回的就是“指向成员的指针”,找本C++ Primer好好补课去。

重复答案有什么意义?

#23


要你去C++ Primer补课,是让你自己找出“指向成员的指针”是C++新增的一种基本数据类型。
它其它什么都不是,它就是它自己。
它能做的(符合C++标准规定的)操作C++ Primer都讲了。

#24


那这个指针能不能转换?或比较大小?

#25


你这个 列子  是 不是 Inside C++ object modal 上的 ?

#26


引用 24 楼 unhappyless 的回复:
那这个指针能不能转换?或比较大小?

C++ Primer上如果讲了可以那就可以,如果没讲可以那就不可以。
自己认真到书上找答案。

#27


没有发现任何异常,编译运行都成功

#28


引用 27 楼 wjb_yd 的回复:
没有发现任何异常,编译运行都成功


可能编译器不同吧,&Point3D::z 咋比较大小呢?

#29


加上 构造函数 
还有成员变量要初始化

#30


Run-Time Check Failure #3 - The variable 'temp' is being used without being initialized.
-vs2008
没初始化是正解。
至于
&Point3D::z 返回的是offset 这话确实没有错
所以printf返回是正确的
但是<<没有对此进行重载,默认的是只是返回bool
基本上,等价于下面的语句
所以为1
cout << "Point3d::x = " << (bool) &Point3d::x << endl;

为了正确的输出
可以尝试下面的代码
float Point3D::*const pm = &Point3D::x;
cout << "Point3d::x = " << (const void *&) pm << endl;

#31


当然重载<<也是可以的。。。加上就可以了
template<class T, typename M>
ostream & operator <<(ostream &os, M T::*pm)
{
os << (const void *&) pm;

return os;
}

#32


引用 31 楼 happyboxman 的回复:
当然重载 < <也是可以的。。。加上就可以了 
template <class T, typename M> 
ostream & operator < <(ostream &os, M T::*pm) 

os < < (const void *&) pm; 

return os; 


====================================

 (const void *&)  能转吗?

 &Point3d::x  我就没法转成任何类型

#33


学习了

#34


引用 3 楼 unhappyless 的回复:
为什么不生成默认构造函数呢?VS2005

生成了默认构造函数的,不过对于float x,y,z;没帮你"默认构造",这不是VS2005的义务.

建议记住:
   在对象构造函数里,将所有成员初始化, 你的责任!
   在使用前将数组初始化, 你的责任!
   在适当的时机将字串无效部分置零, 你可以活得久些!

对于cout<<&Point3D::z<<endl;    // &Point3D::z 返回的是offset ,void* ,那么 cout<< void* 输出的也应该是地址啊,为什么全是1?
实在费解为什么会这么写:
对于 &Point3D::z 编译器给你解释为 (float Point3D::*) 看清楚了吧(不是 float* Point3D:: .... ), 是成员的偏移量, float 只起了个sizetype作用;
如果你用: 
    printf("%d,%d,%d",&Point3D::x,&Point3D::y,&Point3D::z);
输出为:
    0,4,8 // 明白了吧.

如果你用cout的话,实际cout 把 (&Point3D::x) 当成bool量, 谁叫你搞这么奇异的东西....
    operator<<(_Bool _Val)
所以输出为 "1" 了, 为什么 &Point3D::x printf输出0,count输出1呢,哈哈,注意下_Bool吧,自己研究下去...(俺知道,就不说)叫你写这东西

#35


引用 32 楼 unhappyless 的回复:
引用 31 楼 happyboxman 的回复:
当然重载 < <也是可以的。。。加上就可以了 
template <class T, typename M> 
ostream & operator < <(ostream &os, M T::*pm) 

os < < (const void *&) pm; 

return os; 

 

==================================== 

(const void *&)  能转吗? 

&Point3d::x  我就没法转成任何类型


是 float &Point3d::* x,,,,天书一般的东西,怎么理解都行,转就别想了

#36


引用 34 楼 mybabyanddear 的回复:
如果你用cout的话,实际cout 把 (&Point3D::x) 当成bool量, 谁叫你搞这么奇异的东西.... 
    operator < <(_Bool _Val) 


哪里有说明是当bool ?

#37


引用 36 楼 unhappyless 的回复:
引用 34 楼 mybabyanddear 的回复:
如果你用cout的话,实际cout 把 (&Point3D::x) 当成bool量, 谁叫你搞这么奇异的东西.... 
    operator < <(_Bool _Val) 
 

哪里有说明是当bool ?


这个不用说明,你跟踪一下就清楚了,或者看调用堆栈, 的确被当作 bool处理了,值全为 true