C++ C++;在没有对象初始化的情况下调用函数
为什么要运行以下代码C++ C++;在没有对象初始化的情况下调用函数,c++,pointers,object,initialization,C++,Pointers,Object,Initialization,为什么要运行以下代码 #include <iostream> class A { int num; public: void foo(){ num=5; std::cout<< "num="; std::cout<<num;} }; int main() { A* a; a->foo(); return 0; } 我使用gcc编译它,在第10行只得到以下编译器警告: (警告:此函数未初始化时使用
#include <iostream>
class A {
int num;
public:
void foo(){ num=5; std::cout<< "num="; std::cout<<num;}
};
int main() {
A* a;
a->foo();
return 0;
}
我使用gcc编译它,在第10行只得到以下编译器警告:
(警告:此函数未初始化时使用了“a”)
但根据我的理解,这段代码不应该运行吗?当num不存在,因为还没有创建类型为A的对象时,它怎么会将值5赋给num呢
A* a;
a->foo();
调用未定义行为的。最常见的情况是程序崩溃
C++03标准第§4.1/1节规定:
a的左值(3.10)
非函数、非数组类型T可以是
转换为右值。如果T是一个
不完整类型,一个
这种转换是必要的
格式不正确。如果
左值引用不是类型为的对象
并且不是类型的对象
从T派生,或如果对象是
未初始化的程序
必须进行这种转换
未定义的行为。如果T是一个
非类类型,右值的类型
是T的cv不合格版本。
否则,右值的类型为
T
请参见类似主题:
当num不存在,因为还没有创建类型为A的对象时,为什么要将值5赋给num呢
这叫做幸运。但是它不会总是发生代码>是未初始化的指针 您看到的值是垃圾,您很幸运没有以崩溃告终 这里没有初始化 这里没有作业 您的类恰好足够简单,不会显示更严重的问题
A*A(0)代码>将导致崩溃。在某些情况下,未初始化的指针会导致崩溃,并且更容易使用更复杂的类型进行复制
这是处理未初始化指针和对象的结果,它指出了编译器警告的重要性。您还没有初始化*a
试试这个:
#include <iostream>
class A
{
int num;
public:
void foo(){ std::cout<< "num="; num=5; std::cout<<num;}
};
int main()
{
A* a = new A();
a->foo();
return 0;
}
“不吉利”(使调试程序更容易,所以我不认为它是“不吉利的”,真的):
创建对象时,即使不使用关键字new
,也会为该特定对象分配类成员,因为该对象是指向类的指针。因此,您的代码运行良好,并为您提供值num
,但GCC会发出警告,因为您没有显式地实例化对象。代码会产生未定义的行为,因为它试图取消引用未初始化的指针。未定义的行为是不可预测的,不遵循任何逻辑。因此,任何关于代码为什么做某事或不做某事的问题都毫无意义
你在问为什么它会运行?它不跑了。它产生未定义的行为
您询问它如何将5分配给不存在的成员?它不会给任何东西赋值。它产生未定义的行为
您是说输出是5
?错。输出不是5
。没有有意义的输出。代码生成未定义的行为。仅仅因为在你的实验中碰巧打印了5
,就意味着完全没有任何意义,也没有任何有意义的解释。我将(呵呵)向你指出我之前对一个非常类似问题的回答:
基本上,您正在用指针覆盖envs
堆栈变量,因为您没有将envs
添加到main
声明中
由于envs
是一个数组(字符串)数组,它实际上分配得非常多,您将用5
覆盖该列表中的第一个指针,然后再次读取它以使用cout
打印
这就是为什么会发生这种情况的答案。显然,你不应该依赖于此。我认为这就是发生的事情
a->foo()代码>
因为您只是在调用A::foo(A)。
a
是main调用堆栈中的指针类型变量<当访问位置a
时,code>foo()
函数可能会抛出分段错误,但如果没有,则foo()
只从a跳转一些位置,并用值5覆盖4个字节的内存。然后读取相同的值
我是对还是错?请让我知道,我正在学习呼叫堆栈,如果您对我的回答有任何反馈,我将不胜感激
还要看下面的代码
#include<iostream>
class A {
int num;
public:
void foo(){ num=5; std::cout<< "num="; std::cout<<num;}
};
int main() {
A* a;
std::cout<<"sizeof A is "<<sizeof(A*)<<std::endl;
std::cout<<"sizeof int is "<<sizeof(int)<<std::endl;
int buffer=44;
std::cout<<"buffer is "<<buffer<<std::endl;
a=(A*)&buffer;
a->foo();
std::cout<<"\nbuffer is "<<buffer<<std::endl;
return 0;
}
#包括
甲级{
int-num;
公众:
void foo(){num=5;std::coutI怀疑该值是否为垃圾。如果我将foo中num的值从num=5更改为num=any数字,我会在输出时得到该数字。它肯定是垃圾-通过写入num的值,您正在覆盖内存中附近其他对象的地址。Apoorva Iyer,您显然不理解“未定义的行为。”哦,那样的话。所以我覆盖了其他一些垃圾地址!我以为你的意思是num的值是垃圾。这更有意义。谢谢!另外,由于缺少赋值而“获取”的值是垃圾(特别是)。除此之外,你要么访问有效的内存地址,要么访问无效的内存地址(==崩溃或非常神秘的行为)。我故意没有初始化*a。重点是我可以在foo()中设置'num'的值没有初始化*a!可能是+1的重复。另外一个问题:如果没有成员num
,你应该能够期待这项工作吗?例如,如果它只包含std::cout@Merlyn Morgan Graham:不。这里的代码反引用了未初始化的指针。这是未定义的行为(即程序可能做任何事情(包括看起来工作))@Martin:我想我可以看到规范没有定义这一点,所以你不应该依赖它,但是
// uninitialized memory 0x00000042 to 0x0000004B
A* a;
// a = 0x00000042;
*a = "lalalalala";
// "Nothing" happens
void* a;
// a = &main;
*a = "lalalalala";
// Not good. *Might* cause a crash.
// Perhaps someone can tell me exactly what'll happen?
#include<iostream>
class A {
int num;
public:
void foo(){ num=5; std::cout<< "num="; std::cout<<num;}
};
int main() {
A* a;
std::cout<<"sizeof A is "<<sizeof(A*)<<std::endl;
std::cout<<"sizeof int is "<<sizeof(int)<<std::endl;
int buffer=44;
std::cout<<"buffer is "<<buffer<<std::endl;
a=(A*)&buffer;
a->foo();
std::cout<<"\nbuffer is "<<buffer<<std::endl;
return 0;
}