我在学习C ++时遇到了一个问题,其中函数中的局部变量被传递给另一个函数中具有相同名称的局部变量,这两个函数都在main()中运行。
运行时,
class Persistence(object):
def __init__(self):
self.counter1 = 0
self.counter2 = 0
def digitize(self, num):
return [int(digit) for digit in str(num)]
def sum_digits(self, num):
return sum(self.digitize(num))
def times_digits(self, num):
the_list = self.digitize(num)
the_product = 0
for digit in the_list:
the_product = the_product * digit
return the_product
def additive(self, num):
sum1 = self.sum_digits(num)
list1 = []
list1 = self.digitize(sum1)
if len(list1) > 1:
self.counter1 += 1
self.additive(sum1)
return sum1, self.counter1
def multiplicative(self, num):
prod1 = self.times_digits(num)
list1 = []
list1 = self.digitize(prod1)
if len(list1) > 1:
self.counter2 += 1
self.multiplicative(prod1)
return prod1, self.counter2
c = Persistence()
print c.additive(5)
print c.multiplicative(5)
输出:
#include <iostream>
using namespace std;
void next();
void again();
int main()
{
int a = 2;
cout << a << endl;
next();
again();
return 0;
}
void next()
{
int a = 5;
cout << a << endl;
}
void again()
{
int a;
cout << a << endl;
}
我期望again()会说null或0因为'a'再次在那里声明,但它似乎使用了'a'在next()中赋值的值。
为什么next()将局部变量'a'的值传递给again()如果'a'再次在again()中声明?
答案 0 :(得分:7)
http://en.cppreference.com/w/cpp/language/ub
你是对的,一个未初始化的变量是禁忌。但是,您可以声明一个变量,直到稍后才初始化它。内存被保留以容纳整数,但是在你执行此操作之前,该内存中的值恰好可以是任何内容。有些编译器会自动将变量初始化为垃圾值(以帮助您捕获错误),有些将自动初始化为默认值,而有些则根本不执行任何操作。 C ++本身没有任何承诺,因此它是未定义的行为。在您的情况下,使用您的简单程序,可以很容易地想象编译器如何创建汇编代码,重复使用完全相同的内存而不改变它。然而,这是盲目的运气,即使在你的简单程序中也不能保证会发生。这些类型的错误实际上可能是相当隐蔽的,因此请将其作为规则:对未初始化的变量保持警惕。
答案 1 :(得分:5)
* 内置类型的未初始化的非static
局部变量(phew!是满口)具有不确定值。除char
类型外,使用该值会正式生成未定义行为,a.k.a。 UB 。任何事情都可能发生,包括你看到的行为。
显然,使用您的编译器和选项,在调用a
时用于next
的堆栈区域在调用again
之前不用于其他内容,其中被重用于a
中的again
,现在具有与之前相同的值。
但你不能依赖它。对于UB,任何事情都可能发生,或者一无所获。
* 或者更一般地说是POD类型, Plain Old Data 。标准的规范有点复杂。在C ++ 11中,它从§8.5/ 11开始,“如果没有为对象指定初始化器,则对象是默认初始化的;如果没有执行初始化,则具有自动或动态存储持续时间的对象具有不确定的值。“其中“自动...存储持续时间”包括本地非static
变量的情况。并且通过§8.5/ 6定义默认初始化的两种方式可以发生“无初始化”,即通过无操作默认构造函数,或通过不属于类或数组类型的对象。
功能
答案 2 :(得分:1)
这完全是巧合和未定义的行为。
发生了什么事情是你有两个紧接着叫做的函数。两者都将具有或多或少相同的函数序言,并且都在堆栈上保留完全相同大小的变量。
由于没有其他变量在播放,并且在调用之间没有修改堆栈,你恰好在第二个函数中结束了局部变量&#34;登陆&#34;与前一个函数的局部变量位于同一位置。
显然,依靠它并不好。事实上,它是始终初始化变量的原因的完美示例!