在IL中,标号(label)是一个末尾带有冒号(即:)的名称。它使我们能够从代码的一部分无条件地跳转到另一部分。我们经常在由反编译器生成的IL代码中看到这个标号。例如:

IL_0000: ldstr      "hi"

IL_0005: call       void [mscorlib]System.Console::WriteLine(class System.String)

IL_000a: call       void zzz::abc()

IL_000f: ret

在冒号前面的词就是标号。在下面给出的程序中,我们在函数abc中创建一个名为a2的标号。指令br用于随时跳转到程序中的任何标号。

a.il

.assembly mukhi {}

.class private auto ansi zzz extends System.Object

{

.method public hidebysig static void vijay() il managed

{

.entrypoint

.locals (int32 V_0,class zzz V_1)

newobj instance void zzz::.ctor()

stloc.1

call int32 zzz::abc()

stloc.0

ldloc.0

call void [mscorlib]System.Console::WriteLine(int32)

ret

}

.method private hidebysig static int32 abc() il managed

{

.locals (int32 V_0)

ldc.i4.s   20

br.s a2

ldc.i4.s   30

a2: ret

}

}

Output

20

函数abc示范了这个概念。在这个函数中,代码绕过了指令ldc.i4.s 30。因此,返回值显示为20而不是30。从而,IL使用br指令来无条件地跳跃到代码的任何部分。(程序集指令br获取4字节,而在.sr之前的br,即br.s获取1字节,对于每个标记为.s的指令,解释都是相同的。)

br指令是IL得以运转的关键组件之一。

a.cs

class zzz

{

static bool i = true;

public static void Main()

{

if (i)

System.Console.WriteLine("hi");

}

}

a.il

.assembly mukhi {}

.class private auto ansi zzz extends System.Object

{

.field private static bool i

.method public hidebysig static void vijay() il managed

{

.entrypoint

ldsfld     bool zzz::i

brfalse.s IL_0011

ldstr      "hi"

call       void [mscorlib]System.Console::WriteLine(class System.String)

IL_0011: ret

}

.method public hidebysig specialname rtspecialname static void .cctor() il managed

{

ldc.i4.1

stsfld     bool zzz::i

ret

}

}

Output

hi

在我们的C#程序中,我们将静态变量初始化为true值。

l 静态变量,如果它们是字段,就会在静态构造函数.cctor中被初始化。这会在上面的程序中显示。

l 另一方面,局部变量在它们所在的函数中被初始化。

放置在栈上的静态构造函数中。即使同时在C#和IL中定义了字段i,还是没有true或false这样的符号。

的别名。

布尔运算符TRUE或FALSE是由C#引进的关键字,用来使程序员的工作更加轻松。由于IL不直接支持这些关键字,所以它会替代地使用数字1或0。

指令ldsfld把静态变量的值加载到栈上。指令brfalse对栈进行扫描。如果它找到了数字1,它就会将其解释为TRUE,而如果它找到了数字0,它就会将其解释为FALSE。

或TRUE,所以它不会跳转到标号IL_0011。在从C#到IL的转换中,ildasm使用以IL_开始的名称来代替标号。

指令brfalse表示“如果FALSE就跳转到标号”。这不同于br,后者总是会导致一个跳转。从而,brfalse是一个有条件的跳转指令。

在IL中没有提供if语句功能的指令。C#中的if语句会被转换为IL中的转移(branch)指令。我们所处的任何汇编器,都没有像if结构体这样的高级概念。

可以看到,我们刚刚学到的那些知识,对于我们掌握IL是非常重要的。这将帮助我们获得——区别关于哪个概念是IL的一部分而哪些是由编程语言的设计者引进——的能力

尤其需要注意的是,如果IL不支持某个特性,它就不能用任何.NET编程语言实现。从而,熟悉IL所支持的各种概念的重要性——怎么强调都不过分。

a.cs

class zzz

{

static bool i = true;

public static void Main()

{

if (i)

System.Console.WriteLine("hi");

else

System.Console.WriteLine("false");

}

}

a.il

.assembly mukhi {}

.class private auto ansi zzz extends System.Object

{

.field private static bool i

.method public hidebysig static void vijay() il managed

{

.entrypoint

ldsfld bool zzz::i

brfalse.s IL_0013

ldstr "hi"

call void [mscorlib]System.Console::WriteLine(class System.String)

br.s IL_001d

IL_0013: ldstr      "false"

call void [mscorlib]System.Console::WriteLine(class System.String)

IL_001d: ret

}

.method public hidebysig specialname rtspecialname static void .cctor() il managed

{

ldc.i4.1

stsfld     bool zzz::i

ret

}

}

Output

hi

l ,正如这个例子中的那样,它调用带有参数hi的WriteLine函数,并随后使用无条件跳转指令br,跳转到标号IL_001d。

,代码跳转到IL_0013,并且WriteLine函数会打印出false。

从而,为了在IL中实现if-else结构,需要一个有条件跳转和一个无条件跳转。如果我们使用多个if-else语句,那么IL代码的复杂度就会动态增加。

现在,可以看出编译器的编写者的智商了。

a.cs

class zzz

{

public static void Main()

{

}

void abc( bool a)

{

if (a)

{

int i = 0;

}

if ( a)

{

int i = 3;

}

}

}

a.il

.assembly mukhi {}

.class public auto ansi zzz extends [mscorlib]System.Object

{

.field private int32 x

.method public hidebysig static void vijay() il managed

{

.entrypoint

ret

}

.method private hidebysig instance void abc(bool a) il managed

{

.locals (int32 V_0,int32 V_1)

ldarg.1

brfalse.s IL_0005

ldc.i4.0

stloc.0

IL_0005: ldarg.1

brfalse.s IL_000a

ldc.i4.3

stloc.1

IL_000a: ret

}

}

C#编程语言就更复杂了。在内部的一组括号中,我们不能创建之前已经在外部创建的变量。上面的C#程序在语法上是正确的,因为括号都是在同一级别上。

在IL中,会稍微简单一些。这两个i会变成两个单独的变量V_0和V_1。因此,IL不会暴露施加在变量上的任何约束。

a.cs

class zzz

{

static bool i = true;

public static void Main()

{

while (i)

{

System.Console.WriteLine("hi");

}

}

}

a.il

.assembly mukhi {}

.class private auto ansi zzz extends System.Object

{

.field private static bool i

.method public hidebysig static void vijay() il managed

{

.entrypoint

br.s IL_000c

IL_0002: ldstr      "hi"

call void [mscorlib]System.Console::WriteLine(class System.String)

IL_000c: ldsfld     bool zzz::i

brtrue.s IL_0002

ret

}

.method public hidebysig specialname rtspecialname static void .cctor() il managed

{

ldc.i4.1

stsfld     bool zzz::i

ret

}

}

当看到反汇编的代码时,你将理解为什么程序员不以编写IL代码来谋生。即使一个简单的while循环,在转换为IL后都会变得惊人的复杂。

对于一个while结构,会创建一个到标号IL_000c的无条件跳转,它位于函数的结尾。这里,它加载静态变量i的值到栈上。

下一个指令brtrue,做的事情和指令brfalse所做的正好相反。实现如下:

l ,那么它会跳转到标号IL_0002。然后值hi被放到栈上并且WriteLine函数会被调用。

,那么程序将跳转到ret指令。

上面的程序,正如你所看到的那样,并不打算停止。它会继续流动,就像一个起源于一个巨大冰川的水流。

a.cs

class zzz

{

static int i = 2;

public static void Main()

{

i = i + 3;

System.Console.WriteLine(i);

}

}

a.il

.assembly mukhi {}

.class private auto ansi zzz extends System.Object

{

.field private static int32 i

.method public hidebysig static void vijay() il managed

{

.entrypoint

ldsfld int32 zzz::i

ldc.i4.3

add

stsfld int32 zzz::i

ldsfld int32 zzz::i

call void [mscorlib]System.Console::WriteLine(int32)

ret

}

.method public hidebysig specialname rtspecialname static void .cctor() il managed

{

ldc.i4.2

stsfld     bool zzz::i

ret

}

}

Output

5

IL没有操作符用来做两个数字的加法,而是使用add指令。

个数字。

一旦指令被执行了,IL中的大多数指令就会摆脱栈上的参数,也就是该指令要操作的参数。

使用指令stsfld将静态变量i初始化为加法的结果总和。剩下的代码直接显示了变量i的值。

在IL中没有++操作符的等价物。它会被转换为指令ldc.i4.1。同样,两个数字相乘,需要使用mul指令;相减,就使用sub指令,等等。它们在IL中都有等价物。之后的代码保持不变。

a.cs

class zzz

{

static bool i;

static int j = 19;

public static void Main()

{

i = j > 16;

System.Console.WriteLine(i);

}

}

a.il

.assembly mukhi {}

.class private auto ansi zzz extends System.Object

{

.field private static bool i

.field private static int32 j

.method public hidebysig static void vijay() il managed

{

.entrypoint

ldsfld     int32 zzz::j

ldc.i4.s   16

cgt

stsfld     bool zzz::i

ldsfld     bool zzz::i

call void [mscorlib]System.Console::WriteLine(bool)

ret

}

.method public hidebysig specialname rtspecialname static void .cctor() il managed

{

ldc.i4.s   19

stsfld int32 zzz::j

ret

}

}

Output

True

(FALSE)放到栈上。这个值随后被存储到变量i中。使用WritleLine函数,就会生成布尔值的输出,从而我们看到显示True。

个。从而我们看到IL具有它自己的一套逻辑操作符,对基本的逻辑运算进行内部处理。

a.cs

class zzz

{

static bool i;

static int j = 19;

public static void Main()

{

i = j == 16;

System.Console.WriteLine(i);

}

}

a.il

.assembly mukhi {}

.class private auto ansi zzz extends System.Object

{

.field private static bool i

.field private static int32 j

.method public hidebysig static void vijay() il managed

{

.entrypoint

ldsfld     int32 zzz::j

ldc.i4.s   16

ceq

stsfld     bool zzz::i

ldsfld     bool zzz::i

call void [mscorlib]System.Console::WriteLine(bool)

ret

}

.method public hidebysig specialname rtspecialname static void .cctor() il managed

{

ldc.i4.s   19

stsfld int32 zzz::j

ret

}

}

Output

False

操作符==就是EQUALITY操作符。它也需要栈上的2个操作数(operand)来检查相等性。此后它使用ceq指令来检查相等性。如果相等,它会把值1(TRUE)放到栈上,如果不相等,它会把值0(FALSE)放到栈上。指令ceq是IL的逻辑指令集的不可缺少的一部分。

a.cs

class zzz

{

static bool i;

static int j = 19;

public static void Main()

{

i = j >= 16;

System.Console.WriteLine(i);

}

}

a.il

.assembly mukhi {}

.class private auto ansi zzz extends System.Object

{

.field private static bool i

.field private static int32 j

.method public hidebysig static void vijay() il managed

{

.entrypoint

ldsfld     int32 zzz::j

ldc.i4.s   16

cgt

ldc.i4.0

ceq

stsfld     bool zzz::i

ldsfld     bool zzz::i

call void [mscorlib]System.Console::WriteLine(bool)

ret

}

.method public hidebysig specialname rtspecialname static void .cctor() il managed

{

ldc.i4.s   19

stsfld int32 zzz::j

ret

}

}

Output

False

个融合在一起的条件。

在>=的情况中,IL首先使用cgt指令来检查第1个数字是否大于第2个数字。如果是,它将返回值1,否则就返回值0。如果第1个条件是FALSE,那么ceq指令将会检查这2个数字是否相等。如果相等,它就返回TRUE,否则就返回FALSE。

放到栈上。

,所以它会返回TRUE。

或TRUE。

如果你不能理解上面的解释,那么就从源代码中移除ldc.i4.0和ceq这两行,并观察输出。

a.cs

class zzz

{

static bool i;

static int j = 19;

public static void Main()

{

i = j != 16;

System.Console.WriteLine(i);

}

}

a.il

.assembly mukhi {}

.class private auto ansi zzz extends System.Object

{

.field private static bool i

.field private static int32 j

.method public hidebysig static void vijay() il managed

{

.entrypoint

ldsfld     int32 zzz::j

ldc.i4.s   16

ceq

ldc.i4.0

ceq

stsfld     bool zzz::i

ldsfld     bool zzz::i

call void [mscorlib]System.Console::WriteLine(bool)

ret

}

.method public hidebysig specialname rtspecialname static void .cctor() il managed

{

ldc.i4.s   19

stsfld int32 zzz::j

ret

}

}

Output

True

个ceq指令用来检查栈上的值是否相等。如果它们是相等的,它就会返回TRUE;否则就返回FALSE。

个ceq的结果是TRUE,那么最后的答案就是FALSE,反之亦然。

这确实是一种独创的方式来对一个值求否。

a.cs

class zzz

{

static int i = 1;

public static void Main()

{

while ( i <= 2)

{

System.Console.WriteLine(i);

i++;

}

}

}

a.il

.assembly mukhi {}

.class private auto ansi zzz extends System.Object

{

.field private static int32 i

.method public hidebysig static void vijay() il managed

{

.entrypoint

br.s IL_0018

IL_0002: ldsfld     int32 zzz::i

call void [mscorlib]System.Console::WriteLine(int32)

ldsfld int32 zzz::i

ldc.i4.1

add

stsfld int32 zzz::i

IL_0018: ldsfld int32 zzz::i

ldc.i4.2

ble.s IL_0002

ret

}

.method public hidebysig specialname rtspecialname static void .cctor() il managed

{

ldc.i4.s   1

stsfld int32 zzz::i

ret

}

}

Output

1

2

在介绍完条件语句之后,我们现在将关注于while循环。这种转换是必须的,因为我们在诸如while这样的循环中使用条件语句。包括条件的while循环稍微有点复杂。

让我们直接到标号IL_0018上,它位于IL代码中zzz函数的结尾。这里存在着一个条件。i的值(即1)被存储到栈上。接下来,常量2被放到栈上。

如果你再次访问C#代码,那么while语句中的条件就是i <= 2。指令ble.s是基于两个构造函数的:cgt和brfalse。这个指令检查了第1个值(即变量i)是否小于等于第2个值。如果是,它就会指示程序跳转到标号IL_0002。如果不是,程序就移动到下一个指令。

因此,像ble这样的指令使我们的工作更加容易,因为我们不必再次使用cgt和brfalse指令。

在C#中,while结构的条件出现在顶部,但是条件的代码出现在底部。在转换为IL时,在while结构体之间被执行的代码,会被放置在条件代码之上。

a.cs

class zzz

{

static int i = 1;

public static void Main()

{

for ( i = 1; i <= 2 ; i++)

{

System.Console.WriteLine(i);

}

}

}

a.il

.assembly mukhi {}

.class private auto ansi zzz extends System.Object

{

.field private static int32 i

.method public hidebysig static void vijay() il managed

{

.entrypoint

ldc.i4.1

stsfld     int32 zzz::i

br.s       IL_001e

IL_0008: ldsfld     int32 zzz::i

call       void [mscorlib]System.Console::WriteLine(int32)

ldsfld     int32 zzz::i

ldc.i4.1

add

stsfld int32 zzz::i

IL_001e: ldsfld     int32 zzz::i

ldc.i4.2

ble.s IL_0008

ret

}

.method public hidebysig specialname rtspecialname static void .cctor() il managed

{

ldc.i4.s   1

stsfld int32 zzz::i

ret

}

}

Output

1

2

老生常谈,while和for结构提供了相同的功能,可以互相转换。

个分号之前的代码只能被执行一次。因此,将要被初始化的变量i,位于循环的外面。然后,我们无条件跳转到标号IL_001e,以检查i的值是否小于2。如果结果为TRUE,那么代码跳转到标号IL_0008,它是for语句这段代码的开始点。

,而条件会被一次又一次的检查。

a.cs

public class zzz

{

public static void Main()

{

int i;

i = 1;

while ( i <= 2)

{

System.Console.Write(i);

i++;

}

i = 1;

do

{

System.Console.Write(i);

i++;

} while ( i <= 2);

}

}

a.il

.assembly mukhi {}

.class private auto ansi zzz extends [mscorlib]System.Object

{

.method public hidebysig static void vijay() il managed

{

.entrypoint

.locals (int32 V_0)

ldc.i4.1

stloc.0

br.s       IL_000e

IL_0004:  ldloc.0

call       void [mscorlib]System.Console::Write(int32)

ldloc.0

ldc.i4.1

add

stloc.0

IL_000e: ldloc.0

ldc.i4.2

ble.s      IL_0004

ldc.i4.1

stloc.0

IL_0014: ldloc.0

call       void [mscorlib]System.Console::Write(int32)

ldloc.0

ldc.i4.1

add

stloc.0

ldloc.0

ldc.i4.2

ble.s      IL_0014

ret

}

}

Output

1212

在C#中,do循环和while循环之间的区别是——条件在什么位置被检查。

l 在do-while循环中,条件会在循环的结尾被检查。这意味着循环中的代码至少会被调用一次。

l 在while循环中,条件会在循环的开始被检查。因此,代码可能从来都不会被执行。

放到栈上,并初始化变量i或V_1。

l 在while循环中,我们首先跳转到标号IL_000e,也就是检查条件——变量是否小于等于2——的地方。如果返回TRUE,我们就跳转到标号IL_0004。

l 在do-while循环中,首先Write函数会被执行,随后包括在花括号{}中的剩余代码将会被执行。当到达花括号{}中代码的最后一行时,条件才会被检查。

因此,在IL中写一个do-while循环要比写一个while循环简单得多,因为条件会直接在循环的末尾被检查。

a.cs

public class zzz

{

public static void Main()

{

int i ;

for ( i = 1; i<= 10 ; i++)

{

if ( i == 2)

break;

System.Console.WriteLine(i);

}

}

}

a.il

.assembly mukhi {}

.class private auto ansi zzz extends [mscorlib]System.Object

{

.method public hidebysig static void vijay() il managed

{

.entrypoint

.locals (int32 V_0)

ldc.i4.1

stloc.0

br.s       IL_0014

IL_0004: ldloc.0

ldc.i4.2

bne.un.s   IL_000a

br.s       IL_0019

IL_000a: ldloc.0

call       void [mscorlib]System.Console::WriteLine(int32)

ldloc.0

ldc.i4.1

add

stloc.0

IL_0014: ldloc.0

ldc.i4.s   10

ble.s      IL_0004

IL_0019:  ret

}

}

Output

1

break语句强迫退出for循环、while循环或do-while循环。和往常一样,我们跳转到标号IL_0014,也就是变量V_0或i的值被放置到栈上的地方。然后,我们把条件值10放到栈上,并使用ble.s指令检查i是小于还是大于10。

  • 如果小于,我们就进入到循环中的标号IL_0004。我们再次把变量i的值放到栈上,并把if语句的值2放到栈上。然后,我们使用bne指令——它是ceq指令和brfalse指令的组合。
  • 如果变量V_0为TRUE,break语句就能确保——使用br.s指令跳转到标号IL_0019处的ret语句从而退出loop循环。

a.cs

public class zzz

{

public static void Main()

{

int i ;

for ( i = 1; i<= 10 ; i++)

{

if ( i == 2)

continue;

System.Console.WriteLine(i);

}

}

}

a.il

.assembly mukhi {}

.class private auto ansi zzz extends [mscorlib]System.Object

{

.method public hidebysig static void vijay() il managed

{

.entrypoint

.locals (int32 V_0)

ldc.i4.1

stloc.0

br.s       IL_0014

IL_0004: ldloc.0

ldc.i4.2

bne.un.s   IL_000a

br.s       IL_0010

IL_000a: ldloc.0

call       void [mscorlib]System.Console::WriteLine(int32)

IL_0010: ldloc.0

ldc.i4.1

add

stloc.0

IL_0014: ldloc.0

ldc.i4.s   10

ble.s      IL_0004

ret

}

}

continue语句控制for循环到达结束位置。当if语句结果为TRUE时,程序将绕过WriteLine函数而跳转到循环的结束。然后,代码将在标号IL_0010继续执行,这里,变量V_0的值会增加1。

在break和continue语句之间的主要区别如下所示:

l 在break语句中,程序会跳出循环。

l 在continue语句中,程序绕过剩下的语句,跳转到循环的结尾。

goto语句也能到达相同的功能。从而,break语句、continue语句或goto语句,在转换为IL时,都会被转换为相同的br指令。

下面的程序示范了C#中的goto语句会被直接转换为IL中的br语句。

a.cs

public class zzz

{

public static void Main()

{

goto aa;

aa: ;

}

}

a.il

.assembly mukhi {}

.class private auto ansi zzz extends [mscorlib]System.Object

{

.method public hidebysig static void vijay() il managed

{

.entrypoint

br.s       IL_0002

IL_0002: ret

}

}

C#中一个简单的goto语句,会被转换为IL中的br指令。在C#这样的语言中使用goto被认为是不恰当的,但是,它在IL中的等价物——br指令,对于实现诸如if语句、循环等各种结构而言,却是极其有用的。因此,在编程语言中的禁忌,在IL中却是极其有用的。

a.cs

public class zzz

{

public static void Main()

{

int j;

for ( int i = 1; i <= 2 ; i++)

System.Console.Write(i);

}

}

a.il

.assembly mukhi {}

.class private auto ansi zzz extends [mscorlib]System.Object

{

.method public hidebysig static void vijay() il managed

{

.entrypoint

.locals (int32 V_0,int32 V_1)

ldc.i4.1

stloc.1

br.s       IL_000e

IL_0004: ldloc.1

call       void [mscorlib]System.Console::Write(int32)

ldloc.1

ldc.i4.1

add

stloc.1

IL_000e: ldloc.1

ldc.i4.2

ble.s      IL_0004

ret

}

}

Output

12

这个例子解释了for循环。我们在Main函数中创建了一个变量j,在for语句中创建了一个变量i。在C#中,这个变量i只在for循环中是可见的。因此,这个变量的作用域是受限制的。

但是,转换到IL时,所有的变量都具有相同的作用域。这是因为,变量作用域的概念对IL而言有所不同。因此,取决于C#编译器所执行的变量作用域规则。因此,我们能判断出——所有的变量在IL中具有相同的作用域和可见性。

《C# to IL》第三章 选择和循环的更多相关文章

  1. Java语言程序设计(基础篇) 第三章 选择

    第三章 选择 3.8 计算身体质量指数 package com.chapter3; import java.util.Scanner; public class ComputeAndInterpret ...

  2. Java 第三章 选择结构

    第三章   选择结构 if基本语法: if(条件){// 表达式 // 代码块 } eg: int a = 10; if(a > 1){ System.out.println("内容& ...

  3. Python基础三(选择,循环)

    序 首先我们知道程序的执行有三种结构:顺序.选择.循环三种结构,而为了方便我们书写和多次利用我们就需要把一段代码封装器来,这就是方法.今天我就说的是程序的基本结构的格式和方法. 注:所有的程序都可以通 ...

  4. Java 第三章 选择结构1

    选择结构(一) 会使用基本的 if 选择结构 掌握逻辑运算符,掌握多重 if 选择结构 , 掌握嵌套 if 选择 结构 为什么需要 if 选择结构 例如: 如果张浩的 java 考试成绩大于 98分, ...

  5. 使用java理解程序逻辑 第三章 选择结构一

    if 选择结构: if(条件){       代码块  //条件成立后要执行的代码.可以是一条语句,也可以是一组语句 } 可以处理单一或组合条件的情况. if-else 选择结构: if(条件){   ...

  6. Java基础(三)选择和循环结构

    一.选择结构,条件判断 1.if 语句 一个 if 语句包含一个布尔表达式和一条或多条语句.如果布尔表达式的值为 true,则执行 if 语句中的代码块,否则执行 if 语句块后面的代码. impor ...

  7. Shell第三章《for循环》

    Shell循环:for 语法结构: for 变量名 [ in 取值列表 ] do 循环体 done 需求:自动创建10个用户 #!/bin/bash read -p "请输入你要创建的用户名 ...

  8. D3.js的v5版本入门教程(第三章)—— 选择元素和绑定数据

    D3.js的v5版本入门教程(第三章) 在D3.js中,选择元素和绑定元素是最基本的内容,也是很重要的内容,等你看完整个教程后你会发现,这些D3.js教程都是在选择元素和绑定元素的基础上展开后续工作的 ...

  9. [Python笔记][第三章Python选择与循环]

    1月28日学习 Python选择与循环 选择结构 多分枝选择结构 if 表达式 1: 语句块 1 elif 表达式 2: 语句块 2 elif 表达式 3: 语句块 3 ... else : 语句块 ...

随机推荐

  1. 关于select联动的两种做法

    第一种方法: function dong(){      var getSheng = document.getElementById("sheng");      var get ...

  2. Sublime Text2使用规则

    Sublime Text是我发现的有一好用的编辑器,它不单单只支持 python ,几乎支持目前主流的语言,快捷键丰富,可以极大的提高代码开发效率.Sublime Text 网址:http://www ...

  3. 关于boost 的smart_ptr 的使用问题

    boost 的smart_ptr 库中含有好几种智能指针,大家用的最多的应该是shared_ptr ,为啥呢?好用,不用管他啥时候会自动删除等等,而且拷贝和复制都很到位, 但实际上,这个库也有问题,连 ...

  4. 转:在CentOS 7.3使用yum安装 MySql5.6.24

    按照CentOS 6.5的方法在CentOS 7上安装会失败,需要按照下文进行安装. 1.安装rpm包 Linux系统自带的repo是不会自动更新每个软件的最新版本(基本都是比较靠后的稳定版),所以无 ...

  5. MariaDB配置远程访问权限

    首先配置允许访问的用户,采用授权的方式给用户权限 1 GRANT ALL PRIVILEGES ON *.* TO 'root'@'%'IDENTIFIED BY '123456' WITH GRAN ...

  6. Linux命令之ip命令

    linux的ip命令和ifconfig类似,但前者功能更强大,并旨在取代后者.使用ip命令,只需一个命令,你就能很轻松地执行一些网络管理任务.ifconfig是net-tools中已被废弃使用的一个命 ...

  7. 洛谷 P2077 红绿灯 题解

    题目传送门 这道题一秒一秒的扫描一定会超时,所以就用一种O(N)的算法. #include<bits/stdc++.h> using namespace std; ],b[],c[],x= ...

  8. jquery.query.js 插件(示例及简单应用) —— html之间传值

    帮助文档 var url = location.search; > "?action=view&section=info&id=123&debug&te ...

  9. EasyUi – 6.easyui常见问题

    1.进度条 2.JQuery EasyUI弹出对话框解决Asp.net服务器控件无法执行后台代码的方法 3. 三张表的连接查询现在到datagrid里 4.日期组合框DateBox设置readonly ...

  10. s12-day04-work01 简单计算器功能实现

    代码: #!/usr/local/env python3 ''' Author:@南非波波 Blog:http://www.cnblogs.com/songqingbo/ E-mail:qingbo. ...