精华内容
下载资源
问答
  • 循环变量的定义应在循环体内部
    千次阅读
    2017-01-01 15:32:18

    for(int i=0;i<n;i++){
    .......
    }

    我们很常做的一件事就是在for循环里定义一个变量并初始化(如上面定义的i,初始化为1),这个变量有可能是为了做循环限制而定义的,而此时变量只做为for循环的局部变量

    循环结束后就不能再使用i这个变量。

    这是C99规定了一种新的for循环语法,这种语法也是从C++借鉴的,考虑到兼容性不建议使用这种写法。
    文章转载自http://blog.csdn.net/xiaochenhua/article/details/7031339

    更多相关内容
  • 循环外和循环定义变量的区别

    千次阅读 2020-08-10 17:48:38
    } } } } 二、问题 从上面的代码可以看到,TestThread和TestThread2的区别在于map的定义是放在for循环外面还是里面,那么就有一个问题,在写代码的时候到底是要将变量定义在外面还是里面呢。 三、JVM运行时数据区 ...

    一、代码展示

    import java.util.HashMap;
    import java.util.Map;
    
    /**
     * @Package: raymond
     * @ClassName: Test
     * @Author: tanp
     * @Description: ${description}
     * @Date: 2020/8/10 14:12
     */
    public class Test {
    
        public static void main(String[] args) {
            TestThread2 testThread = new TestThread2();
            testThread.start();
        }
    
        static class TestThread extends Thread {
            @Override
            public void run() {
                for(int i=0; i<10; i++){
                    Map<String,Object> map = new HashMap<>();
                    map.put(i+"",i);
                }
            }
        }
    
        static class TestThread2 extends Thread {
            Map<String,Object> map;
            @Override
            public void run() {
                for(int i=0; i<10; i++){
                    map = new HashMap<>();
                    map.put(i+"",i);
                }
            }
        }
    }
    

    二、问题

    从上面的代码可以看到,TestThread和TestThread2的区别在于map的定义是放在for循环外面还是里面,那么就有一个问题,在写代码的时候到底是要将变量定义在外面还是里面呢。

    三、JVM运行时数据区

    首先我们要知道JVM运行时数据区中有几大块,其中的两块分别为栈和堆

    JVM

    JVM栈是线程私有的,每个线程创建的同时都会创建JVM栈,JVM栈中存放的为当前线程中局部基本类型的变量(java中定义的八种基本类型:boolean、char、byte、short、int、long、float、double)、部分的返回结果以及Stack Frame,非基本类型的对象在JVM栈上仅存放一个指向堆上的地址

    堆(Heap

    它是JVM用来存储对象实例以及数组值的区域,可以认为Java中所有通过new创建的对象的内存都在此分配,Heap中的对象的内存需要等待GC进行回收。

    (1)       堆是JVM中所有线程共享的,因此在其上进行对象内存的分配均需要进行加锁,这也导致了new对象的开销是比较大的

    (2)       Sun Hotspot JVM为了提升对象内存分配的效率,对于所创建的线程都会分配一块独立的空间TLAB(Thread Local Allocation Buffer),其大小由JVM根据运行的情况计算而得,在TLAB上分配对象时不需要加锁,因此JVM在给线程的对象分配内存时会尽量的在TLAB上分配,在这种情况下JVM中分配对象内存的性能和C基本是一样高效的,但如果对象过大的话则仍然是直接使用堆空间分配

    (3)       TLAB仅作用于新生代的Eden Space,因此在编写Java程序时,通常多个小的对象比大的对象分配起来更加高效。

    具体的jvm知识可以查看我的这篇博客https://blog.csdn.net/bird_tp/article/details/88560468

    四、循环内和循环外定义变量的本质区别

    结合上面的堆、栈信息,我们可以明白变量的定义是放在栈里面的,变量的实例化对象是放在堆里面的,所以我们前面两个线程中定义map的本质区别在于

    线程TestThread在栈声明了10个栈内存地址,10个堆内存地址,而TestThread2只声明了1个栈内存地址,10个堆内存地址。TestThread2线程在循环实例化map时,只是通过一个栈内存地址移动引用指向了的10个堆内存地址。

    总结起来就是
    1、在循环外面的定义的变量,只在栈中声明了一次;
    2、在循环里面的定义的变量,循环多少次就在栈中声明了多少次;

    五、循环时具体如何定义变量

    放在循环内部定义,确实会多次申请栈帧的内存空间,但其实话说回来,这样对性能的影响其实可以忽略不计,没什么大的问题。因为栈内存的分配非常之快,仅次于寄存器,所以,可以忽略不计。

    总的来说,循环内的话,每次循环内部的局部变量在每次进for循环的时候都要重新定义一遍变量,也就是执行申请内存空间,变量压入堆栈的过程。
    循环外定义的话,for循环一直用的是同一块内存空间,效率比较高,但是变量的作用域就大了,耗内存
    所以,其实内外都可以的,总之就是空间和时间的权衡,看实际情况了,局部变量的数据类型、大小什么的都有关

    下面粘贴下jdk7的hashmap的get方法,我们可以看到Object k就是定义在循环里面的。

    public V get(Object key) {
            if (key == null)
                return getForNullKey();
            int hash = hash(key.hashCode());
            for (Entry<K,V> e = table[indexFor(hash, table.length)];
                 e != null;
                 e = e.next) {
                Object k;
                if (e.hash == hash && ((k = e.key) == key || key.equals(k)))
                    return e.value;
            }
            return null;
        }

    六、总结

    在for循环外面和里面定义变量,对于内存,性能影响其实没有什么多大区别。看个人使用情况而言,对于我个人使用而言,还是习惯定义在外面

    展开全文
  • 关于变量在for循环内外定义的思考

    千次阅读 2021-02-28 18:00:08
    在c#或java里面,我们通常会这样写for循环:for(int i = 0;i<10;i++){ Console.WriteLine(i);}前一阵子,我突发奇想,如果按照...}因为我觉得最上面的那种方式,每次循环都会声明一个变量,说不定会影响效率,于...

    在c#或java里面,我们通常会这样写for循环:

    for(int i = 0;i<10;i++){ Console.WriteLine(i);}

    前一阵子,我突发奇想,如果按照下面这样写,会不会比上面的运行效率高一些:

    int i = 0;

    for(; i<10 ;i++)

    {

    Console.WriteLine(i);

    }

    因为我觉得最上面的那种方式,每次循环都会声明一个变量,说不定会影响效率,于是百度了一下,发现其他人也有这个疑惑,特意百度了一些资料,在此做个综合。

    首先是在内层循环中定义变量到底会不会存在重复分配的问题,这涉及到编译器的优化,不过主流编译器(如vs和gcc)这一块优化都比较好,不会反复分配变量。函数的定义是编译器的事情,运行的时候不存在什么定义,更没有什么开销。

    除非是类对象或者结构体对象, 在for循环里面与外面, 开销可能会不一样.基本数据类型, 那是一样的, 编译器肯定会优化这个东西。

    一般来说, 在进入函数时, 所有的栈变量都分配好空间了. 所以那个for变量写在哪里都是一样的. 具体你可以看一下反汇编代码, 全部就展现在你眼前了,我查看过C#的IL代码,发现两种写法的IL代码是一样的,说明没有区别。

    栈中的空间在编译这个代码的时候大小就确定下来了,运行这个方法时空间就已经分配好了,不要想当然的以为声明一次就要分配一次空间,那是c语言,java可以重用这些超出作用域的空间。只要用javap查看方法字节码,看看使用的局部变量表的大小和使用方式即知java这种基于虚拟机的语言,是跟单纯的C不同,C语言的原则是相信程序员能做好一切,因此它不会帮你做多少事情,需要考虑代码优化,内存占用等。

    而java中的原则就是:要写好的代码而不是快的代码。

    不过,自己在编程的时候要注意不要让上一次的结果影响到下一次循环,比如上一次 a = 3, 当下一次循环在给a赋值的时候出了错误,而你捕获了错误,却没修正a的值,程序继续执行,那么这时候a=3还成立,可能就会有问题了,如果是每次都重新定义,那就不存在这样的问题。

    最后总结:

    对于使用int等基本数据类型作为循环变量,只要你用的优化方面足够给力的主流的编译器,完全不需要关心在循环外还是循环内定义循环变量。

    如果循环变量本身是复杂的对象,建议在循环外定义好,并且在for循环的赋值语句、判断语句中,都要避免重复创建对象。

    展开全文
  • 变量定义在for循环外面还是里面

    千次阅读 2021-03-18 00:08:16
    结论:个人推荐,变量定义在for循环内部 原因: 1.在10亿次的数量级上,耗时上,两者没有区别 2.用javap进行反汇编后,指令码上基本无区别,所以在执行时也无区别(变量定义在for循环外没有赋值为null时,区别只是...

    结论:个人推荐,变量定义在for循环内部

    原因:
    1.在10亿次的数量级上,耗时上,两者没有区别
    2.用javap进行反汇编后,指令码上基本无区别,所以在执行时也无区别(变量定义在for循环外没有赋值为null时,区别只是临时变量表中的位置不同;并赋值为null时,只是多了一个null压栈和出栈)
    2.50.用gc日志彻底粉碎,变量定义在for循环内,会‘循环创建引用,浪费内存’的错误说法
    3.jdk源码中,变量定义在for循环内部

    过程:
    原本用javap分析完反汇编后就可以结束并得出结论
    结果我突发奇想打算实际证伪下‘循环创建引用,浪费内存’
    然后就有了下面代码中描述的操作,结果分析了半天gc打印的日志,发现两种方式也一样,并没有多出来的‘大量引用占用空间’
    但是又发现,gc日志中显示占用的内存空间与预估占用的内存空间不符(预估方式请参考另一篇文档,计算对象的大小:https://blog.csdn.net/jt781861965/article/details/114813576
    后来才突然惊醒到,经过逃逸分析,这些对象都被直接在栈上分配了,并没有在堆上分配,所以也不存在gc的问题(逃逸分析默认是打开的,具体逃逸分析可参考:https://www.cnblogs.com/gnivor/p/6028001.html

    **关闭逃逸分析后,**1000w次的数量级上,耗时上,两者没有区别(相较于开启逃逸分析,差距还是很大);javap进行反汇编后,指令码与开启逃逸分析时无区别;gc日志中显示的占用内存也是一样多,最后通过计算得出一个对象占用17byte(因为有jvm自身消耗的内存,计算存在误差,因此结果与实际的一个User对象16byte吻合)
    至此,彻底粉碎了,变量定义在for循环内,会‘循环创建引用,浪费内存’的错误说法

    测试代码(vm参数在代码中):

    package com.myspringboot.jvm.foru;
    
    public class ForUserTest {
        //开启逃逸分析使用下面的代码
        //vm参数:-verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8 -XX:+PrintGC  -XX:+PrintGCTimeStamps  -XX:+PrintGCDateStamps -XX:+PrintHeapAtGC -XX:+PrintGCApplicationStoppedTime
        public static void main(String[] args) {
            //填充内存
            byte[] bytes1 = new byte[5 * 1024 * 1024];
            long start = System.currentTimeMillis();
            //考虑到业务场景,在for中获取到对象后,没有后续操作的话,没有意义;所以在new完之后,还进行了简单的操作
            outFor();
            //inFor();
            System.out.println(System.currentTimeMillis() - start);
            //强制gc
            byte[] bytes2 = new byte[5 * 1024 * 1024];
        }
    
        public static void outFor() {
            User user = null;
            for (int i = 0; i < 999999999; i++) {
                user = new User();
                user.setI(i);
                user.getI();
            }
        }
    
        public static void inFor() {
            for (int i = 0; i < 999999999; i++) {
                User user = new User();
                user.setI(i);
                user.getI();
            }
        }
    
    //分隔线=====================================================================================================
    
        //关闭逃逸分析使用下面的代码
        //vm参数:-server -XX:-DoEscapeAnalysis -verbose:gc -Xms400M -Xmx400M -Xmn300M -XX:+PrintGCDetails -XX:SurvivorRatio=8 -XX:+PrintGC  -XX:+PrintGCTimeStamps  -XX:+PrintGCDateStamps -XX:+PrintHeapAtGC -XX:+PrintGCApplicationStoppedTime
    //    public static void main(String[] args) {
    //        long start = System.currentTimeMillis();
    //        //考虑到业务场景,在for中获取到对象后,没有后续操作的话,没有意义;所以在new完之后,还进行了简单的操作
    //        outFor();
    //        //inFor();
    //        System.out.println(System.currentTimeMillis() - start);
    //        //强制gc
    //        byte[] bytes2 = new byte[200 * 1024 * 1024];
    //    }
    //
    //    public static void outFor() {
    //        User user = null;
    //        for (int i = 0; i < 9999999; i++) {
    //            user = new User();
    //            user.setI(i);
    //            user.getI();
    //        }
    //    }
    //
    //    public static void inFor() {
    //        for (int i = 0; i < 9999999; i++) {
    //            User user = new User();
    //            user.setI(i);
    //            user.getI();
    //        }
    //    }
    }
    
    package com.myspringboot.jvm.foru;
    
    public class User {
        private int i;
    
        public int getI() {
            return i;
        }
    
        public void setI(int i) {
            this.i = i;
        }
    }
    

    用javap对class文件进行反汇编:

    javap -c -l -v ForUserTest.class 
    

    运行时常量池
    在这里插入图片描述

    outFor()
    在这里插入图片描述

    inFor()
    在这里插入图片描述

    对其中的outFor()方法的反汇编指令码进行了解释

             0: aconst_null
    (将null压栈)
    (栈:null)
             1: astore_0
    (弹出,将null放到局部变量表‘0’位置)
    (栈:)
    (局部变量表‘0’位置:null)
             2: iconst_0
    (0压栈)
    (栈:0)
             3: istore_1
    (弹出,将0放到局部变量表‘1’位置)
    (栈:)
    (局部变量表‘1’位置:0)
             4: iload_1
    (将局部变量表‘1’位置的值压栈)
    (栈:0)
             5: ldc           #8                  // int 999999999
    (将运行时常量池中8位置的值999999999压栈)
    (栈:0999999999)
             7: if_icmpge     34
    (弹出栈中中的两个值,并进行比较,当局部变量表‘1’位置的值大于等于999999999时,跳转到34行开始执行;否则接着顺序执行)
    (栈:)
            10: new           #9                  // class com/myspringboot/jvm/foru/User
    (从运行时常量池中9位置的值找到class对象,分配空间,类属性赋初始值后压栈)
    (栈:0xFF(引用地址))
            13: dup
    (将栈顶的元素复制,并重新压栈(此时栈中有两个相同的元素))
    (栈:0xFF0xFF)
            14: invokespecial #10                 // Method com/myspringboot/jvm/foru/User."<init>":()V
    (从运行时常量池中10位置的值找到init方法,弹出一个元素,对类属性赋默认值,并执行构造方法)
    (栈:0xFF)
            17: astore_0
    (弹出,将0xFF放到局部变量表‘0’位置)
    (栈:)
            18: aload_0
    (将局部变量表‘0’位置的值压栈)
    (栈:0xFF)
            19: iload_1
    (将局部变量表‘1’位置的值压栈)
    (栈:0xFF0)
            20: invokevirtual #11                 // Method com/myspringboot/jvm/foru/User.setI:(I)V
    (从运行时常量池中11位置的值找到setI方法,弹出两个元素,执行setI方法,因为没有返回值,所以不需要压栈)
    (栈:)
            23: aload_0
    (将局部变量表‘0’位置的值压栈)
    (栈:0xFF)
            24: invokevirtual #12                 // Method com/myspringboot/jvm/foru/User.getI:()I
    (从运行时常量池中12位置的值找到getI方法,弹出一个元素,执行getI方法,并将结果压栈)
    (栈:0)
            27: pop
    (将栈顶元素弹出)
    (栈:)
            28: iinc          1, 1
    (将局部变量表‘1’位置的值加1,注意此操作没有压栈、弹出的动作)
    (栈:)
            31: goto          4
    (转到4)
            34: return
    (返回)
    

    开启逃逸分析的vm参数和gc日志
    在这里插入图片描述
    在这里插入图片描述

    关闭逃逸分析的vm参数和gc日志
    在这里插入图片描述
    在这里插入图片描述

    展开全文
  • Python 中的循环语句有 2 种,分别是 while 循环和 for 循环 for 循环语句的执行流程如图 1 所示。 for 循环语句的执行流程图 图 1 for 循环语句的执行流程图 如果我们看一下正式的Python语法规范,我们可以看到...
  • for循环内外定义变量的区别

    万次阅读 2019-05-22 22:06:24
    for循环内部定义基本变量类型,每次执行for循环都重新申明变量,不覆盖之前的值,对于for循环外部定义的基本类型变量,代码如下 var indexOuter:int=-1; var recordIndexOuter:int=indexOuter; for (var...
  • matlab循环定义变量名,定义循环字符串

    万次阅读 多人点赞 2019-07-26 15:16:19
    在matlab的循环中定义循环变量名可以使用下面的语句 for o=1:3 eval(['moudle',num2str(o),'=','num2str(o+1)',';']) end %最后得到的moudle1=2; moudle2=3; moudle3=4; %定义循环字符串 for o=1:3 d=strcat('...
  • 1 shell for循环语法for 变量 in 列表docommand1command2...commandNdone1.1 读取列表中的值#!/bin/bashfor test in apple boy cat dogdoecho The next state is $testdone结果:The next state is appleThe next ...
  • java中for循环怎么定义两个变量

    千次阅读 2021-02-12 13:57:27
    展开全部intb=9,a=1;for(a,b;a<=9&&b>=1;a++,b--){for(inta=1;a<=9;a++){System.out.println(b+"*"+a);... 初始化总是一个赋值语句, 它用来给循环控62616964757a686964616fe59b9ee7ad943...
  • for循环中的变量是局部变量还是全局变量

    万次阅读 热门讨论 2019-08-25 20:39:08
    今天写代码时候发现的知识点,对于大神来说可能这不是什么问题,但是对于像我们这样的新手小白而言,发现这个知识点的喜悦难以言表,所以我也同大家分享一下,希望更多的人不要犯相同的错误! 这是我参照《Python...
  • 今天跟同事讨论一个问题,在for循环的时候,难免要在...百度了一下,一般说法是先定义再new,如方法for2()这样, public class test { public static void main(String[] args) { System.out.println(for1()); ...
  • for循环变量赋值与定义和执行顺序的问题
  • python:循环定义多个变量

    万次阅读 多人点赞 2018-05-18 09:50:10
    我们可能会时长碰到这样一个场景,计算得到一个非固定值(这次是3,下次可能是8),需要根据这个值定义相同数量个变量。实现方式的核心是exec函数,exec函数可以执行我们输入的代码字符串。exec函数的简单例子:&gt...
  • 变量定义循环体内还是循环外?

    千次阅读 2013-07-19 10:38:23
    package test; public class Test1 { public void test() { int c; for(int i = 1; i ; i++) { c = i; } } public void test1() { for(int i = 1;...先标记下,等工作完了来解释。
  • 循环体外定义变量为全局变量循环结束后循环体外定义变量循环内的操作赋值,int main(){ int i=100; int j=2; ........1 for(;i&lt;=200;i++){ // int j=2; ..........2 for(;j&lt;=i;j++){ ...
  • 问: // 方法 A: Widget w; for (int i = 0; i &lt; n; ++i) { w = 取决于 i 的某个值; } // 方法 B: ...Effective C++ 条款 26 有一段话大概是:当一个赋值成本低于一组构造+析构成本,定义...
  • 有N项,每项下面有N个表格,如何控制每项下边的表格显示或者隐藏,想着给table 个name属性,以同样的name开头循环N,让每项下的table name 值相同,然后问题来了,不知道如何在JSP页面定义一个变量并让它随着循环加1...
  • 写这篇文章的原因是我在问答平台看到的一个问题:C++内层循环定义变量和在外面定义比影响大吗?问题来自:http://ask.csdn.net/questions/176270 例如: for(int i=0;i;i++) { for(int j=0;j;j++); } 内...
  • shell for循环总结

    千次阅读 2021-05-17 14:14:52
    1 shell for循环语法for 变量 in 列表docommand1command2...commandNdone1.1 读取列表中的值#!/bin/bashfor test in apple boy cat dogdoecho The next state is $testdone结果:The next state is appleThe next ...
  • 类的定义:类声明和类。基本格式如下: class 类名{ 类 } 特点: 1、类是Java程序的基本要素,一个Java应用程序就是由若干个类所构成; 2、类声明的变量称为对象变量,也简称 对象 ; 3、class 关键字是...
  • 问题描述:用循环时常用到调用不同的文件名变量 用字符串作为变量名: eval() 变量名转化为字符串: inputname() 数字变换成字符: num2str() %小例子:使用for循环调用不同变量变量 load('X.mat'); load('Y....
  • for()循环里面定义变量

    千次阅读 2014-11-29 17:51:39
    不同的作用域内可以使用相同的变量名,优先使用小范围的作用域。 作用域: 全局段、函数段、块 1.全局段定义变量a, main函数中再定义a, 那么main中函数中...比如if分支体, for,while循环体定义变量,其作用域
  • thymeleaf定义变量

    千次阅读 2019-07-25 11:09:49
    razor的模板,就是真的母板,所有公用东西都在母板上,应用页面套用这个母板,只须再定义自己的个性化内容即可。而thymeleaf的所谓模板,不是母板,而是片段集合,公共东西,做成一个个片段,由应用页按...
  • 我在写一个功能如下图的程序:!...由于这个程序要能循环执行,这导致了一个问题: 在第一次循环中,我选择功能1,即创建...因为 static变量定义一次,这样就无法创建表。 所以我到底该怎样写这段代码呢?多谢各位啦~
  • 循环变量定义问题

    千次阅读 2016-04-12 18:06:51
    很多java的初学者,在接触循环的时候很容混乱,理不清楚思路,尤其是在定义变量的时候,不知道变量放在循环外还是循环内,导致程序出现错误,我们该如何解决这类问题? 首先我们应该搞懂循环的本质,循环的过程是...
  • C++循环变量定义生命周期

    千次阅读 2011-05-03 21:27:00
    C++与C的一个最大的不同的是C要求所有变量要在最开始的就声明,而C++的变量是信手拈来,你什么时候想用,你就什么时候声明。这个简单的细节其实隐含了C与C++的设计逻辑有所区别。 C设计的时候其实更多是为编译器...
  • 依次输入每个人的名字然后输入成绩,每个名字后面都跟着每个人的成绩,不是把人名输完输成绩。 然后要求统计每个人几次成绩的和,依次输出每个人姓名以及他们的总成绩。这个怎么做? #include #include #include...
  • golang for循环中声明变量

    千次阅读 2019-11-26 18:19:36
    ##golang for循环中声明变量 与C语言不同 package main import ( "fmt" ) func main() { for i := 0; i < 5; i++ { var v int fmt.Println("v ", v) v = 5 } } 你们先猜一猜打印什么? 看看C循环:...
  • 尽量别在for循环里面定义变量

    万次阅读 2011-12-01 16:04:39
    我们很常做的一件事就是在for循环定义一个变量并初始化(如上面定义的i,初始化为1),这个变量有可能是为了做循环限制而定义的,而此时变量只做为for循环的局部变量 循环结束后就不能使用i这个变量。 这是...
  • 去年写的文章自己也看不懂了,很粗糙,今天重新整理下。 现象:工作中遇到一个大坑,STC11F32设置的运行灯闪烁周期为500ms,大多数是500ms低电平和500ms高电平,但偶尔... 函数中定义变量为16位,如果定义为l...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 588,697
精华内容 235,478
关键字:

循环变量的定义应在循环体内部

友情链接: UART.rar