在这篇文章中,我们将带领您了解为什么在Swift中初始化变量的行上出现“初始化前使用变量”错误?的全貌,同时,我们还将为您介绍有关c–在循环中初始化变量、c–如何使用未初始化的数据有意初始化变量,以便
在这篇文章中,我们将带领您了解为什么在Swift中初始化变量的行上出现“初始化前使用变量”错误?的全貌,同时,我们还将为您介绍有关c – 在循环中初始化变量、c – 如何使用未初始化的数据有意初始化变量,以便valgrind将变量视为未初始化?、c# – 使用null转换为变量的数据类型初始化变量、final变量要么定义时初始化,要么在代码块中初始化的知识,以帮助您更好地理解这个主题。
本文目录一览:- 为什么在Swift中初始化变量的行上出现“初始化前使用变量”错误?
- c – 在循环中初始化变量
- c – 如何使用未初始化的数据有意初始化变量,以便valgrind将变量视为未初始化?
- c# – 使用null转换为变量的数据类型初始化变量
- final变量要么定义时初始化,要么在代码块中初始化
为什么在Swift中初始化变量的行上出现“初始化前使用变量”错误?
我正在努力理解为什么我在使用Swift的iOS项目中遇到此编译器错误。如果我创建以下类:
class InitTest { let a: Int let b: Int let c: Int init () { self.a = 3 self.b = 4 self.c = self.runCalculation() } func runCalculation () -> Int { return self.a * self.b }}
我在self.c = self.runCalculation()
“初始化前使用了变量’self.c’” 这一行上收到编译器错误。
起初我以为这是因为编译器无法验证该runCalculation()
方法是否无法访问self.c
,但是后来我尝试将init方法混入一点:
init () { self.a = 3 self.c = self.runCalculation() self.b = 4}
这次的错误是“在初始化之前使用了变量’self.b’”(在同一self.runCalculation()
行上)。这表明编译器 是
能够检查其性能的方法访问,所以据我可以看到应该有最初的情况下,没有问题的。
当然,这是一个简单的示例,我可以轻松地进行重构以避免调用计算方法,但是在实际项目中,可能会有多个计算,每个计算都可能涉及到很多。我希望能够分离出保持可读性的逻辑。
幸运的是,有一个简单的解决方法:
init () { self.a = 3 self.b = 4 self.c = 0 self.c = self.runCalculation()}
(或使用属性初始化程序let c = 0
),但我想了解为什么编译器在第一个示例中有问题。我是否缺少某些东西,还是不必要的限制?
答案1
小编典典由于两阶段初始化,Swift具有此行为。从Apple的Swift书中:
Swift中的类初始化是一个分为两个阶段的过程。在第一阶段,每个存储的属性都由引入它的类分配一个初始值。一旦确定了每个存储属性的初始状态,便开始第二阶段,并且在考虑将新实例准备使用之前,每个类都有机会自定义其存储属性。
在第一阶段结束之前,类需要某种默认值。定制值是第二阶段的一部分。
Objective-C没有这种行为,因为它总是可以0
为基元和nil
对象提供默认值,但是在Swift中,没有机制可以提供此类默认值。
c – 在循环中初始化变量
我的代码目前看起来像这样:
int nHexCount = 0; int prevstate = sc.state; bool bOnlySpaces = true; bool bIsValidLabel = true; bool bIsHotstring = false; bool bIsValidName = true; bool bIsValidExpStart = false; bool fInExpression = false; bool fInStringBlock = (sc.state == SCE_AHKL_STRINGOPTS || sc.state == SCE_AHKL_STRINGBLOCK); for (; sc.More(); sc.Forward()) { if (sc.atLinestart) { if (!fInStringBlock && sc.state != SCE_AHKL_COMMENTBLOCK) sc.SetState(SCE_AHKL_DEFAULT); // Reset Status prevstate = sc.state; bOnlySpaces = true; bIsValidLabel = true; bIsHotstring = false; bIsValidName = true; bIsValidExpStart = false; fInExpression = false; } ...
因此,每当我的程序在我正在编辑的编辑组件中找到一个新行时,您可以看到大多数这些变量都被重置…
问题是:
是否更好的编程实践声明并初始化for循环中的所有变量,或者我应该像现在这样离开它?
解决方法
// bad int i,j,k; k = 0; for (i = 0; i < X,++i) { j = foo(i); k += j; } bar(k);
……对……
// better int k=0; // needs scope outside loop for (int i = 0; i < X,++i) { int j = foo(i); k += j; } bar(k);
c – 如何使用未初始化的数据有意初始化变量,以便valgrind将变量视为未初始化?
当一些虚假代码从垃圾数据缓冲区中读取时,这将是致命的,或者,例如,当我使用垃圾数据缓冲区时,我应该使用适当的专用缓冲区.
理想情况下,我想让伪代码快速崩溃,因此我在调用写入函数后对数据进行加扰,因此没有人可以使用(并依赖)垃圾数据.
现在我有了一个想法,我可以将未初始化的数据复制到垃圾数据而不是加扰它,因此valgrind可以从垃圾缓冲区中找到所有读取.
我当前的解决方案是new []一些字节,并将未初始化的内容复制到垃圾缓冲区,然后删除[]未初始化的数据.由于未初始化的数据在大多数情况下是0(不幸的是),因此我将其与模式进行异或.对于这么简单的事情,这一切似乎都很复杂.
有没有人想出更好的解决方案?
解决方法
你可以这样做:
#include <memcheck.h> // .... VALGRIND_MAKE_MEM_UNDEFINED(trash_buffer,trash_length);
如果您希望valgrind将数据视为不可访问而不仅仅是单元化,您还可以使用VALGRIND_MAKE_MEM_NOACCESS.
在valgrind外部运行时,这将只有很少的运行时开销.即使不在valgrind中运行,你复制内容的方法也可能很昂贵.
c# – 使用null转换为变量的数据类型初始化变量
List<string> list = (List<string>)null;
有没有理由程序员不只是初始化:
List<string> list = null;
这两者有区别吗?
这是从另一种编程语言迁移的习惯吗?也许C,C或Java?
解决方法
Is there a difference between the two?
没有没有区别.
在ILSpy中,此行列表< string> list =(List< string>)null;更改为List< string> list = null;
Is this a habit that migrated from another programming language?
不能说.可能是,早些时候有一些不同于null的东西然后它被改为null.
List<string> list = (List<string>) Session["List"];
final变量要么定义时初始化,要么在代码块中初始化
以上基于jdk1.8。final变量如果是静态的,要么定义时初始化,要么在静态代码块中初始化。final变量如果不是静态的,要么定义时初始化,要么在非静态代码块中初始化。
静态变量定义时初始化:
静态变量在静态代码块中初始化 :