精华内容
下载资源
问答
  • 在Windows64位环境下.net访问Oracle解决方案 引用地址: ...目前,Windows操作系统可以分成两类,32位和64位(64位也区分x86_64位和Itanium),同时Oracle客户端也做了同样的区分。 在安装和开...
     

    在Windows64位环境下.net访问Oracle解决方案

    引用地址:
    http://blog.csdn.net/zouyujie1127/article/details/6371165

    目前,Windows操作系统可以分成两类,32位和64位(64位也区分x86_64位和 Itanium ),同时Oracle客户端也做了同样的区分。

    在安装和开发的过程中,经常会遇到一些问题,本文就总结了相关的解决方案

    Oracle Instant Client的下载地址

    http://www.oracle.com/technetwork/database/features/instant-client/index-097480.html

    以下所有的说明都是基于Windows64位的(以Windows2008为例)

    1 解决方案(这是最终步骤,其他供参考)

    1 安装Oracle64位客户端(win64_11gR2_client):

    下载页面:

    http://www.oracle.com/technetwork/database/enterprise-edition/downloads/112010-win64soft-094461.html

    下载地址:

    http://download.oracle.com/otn/nt/oracle11g/112010/win64_11gR2_client.zip

     

    已经下载到\\192.168.9.24\常用软件\Oracle\win64_11gR2_client.zip

     

    然后正常安装,并进行数据库连接的配置,比如tnsnames.ora

     

    2 将NetWork Service用户加入Administraotr组中,重启计算机(重要)

    3 新建asp.net网站,配置程序的调试模式为使用IIS,不要使用WebServer,这样就可以调试了

    4 由于Webserver是32位的程序,因此如果要使用webserver进行调试,可以考虑安装32位的Oracle客户端(没有进行测试)。

    注意:对于已经安装了32位Oracle客户端的情况,本次没有测试

    2安装顺序

    http://wangyj.blog.163.com/blog/static/85232558201081971322105/

    安装Oracle 11g Release 2 ODAC 11.2.0.1.2 with Oracle Developer Tools for Visual Studio,配置服务器tnsnames,使用SQLPLUS测试成功连接。

    启动IIS,发布.NET连接ORACLE的应用,测试,报"System.Data.OracleClient 需要Oracle 客户端软件8.1.7 或更高版本"错误。解决:将ORACLE安装目录为Network Service用户赋读和执行权,并传递到所有子目录。

    重启动IIS,报“尝试加载 Oracle 客户端库时引发 BadImageFormatException。如果在安装 32 位 Oracle 客户端组件的情况下以 64 位模式运行,将出现此问题。 ”解决:下载并解压instantclient_11_2的X64版本,放到ORACLE安装目录下,并在PATH路径中搜索在前。

    重启动IIS,报“ORA-12154: TNS:could not resolve the connect identifier specified”错误。解决:指定环境变量TNS_ADMIN到tnsnames.ora所在目录。

    重启动IIS,.NET应用连接数据库服务器成功。

     

    3 在asp.net中,不用使用Webdev进行调试,必须使用IIS调试

    http://www.cnblogs.com/studyzy/archive/2010/10/28/1863056.html

    我们平时使用的都是32位的机器进行开发,装的都是32位的软件,但是我们的服务器一般都是64位的,所以有时也需要在64位的环境下装一个VS调试程序。最近遇到的一个问题就是一个同事换了一个电脑,用的是X64的Windows 2008作为操作系统,要进行Oracle的数据库连接,所以也装了64位的Oracle客户端。如果是控制应用项目或者WinForm项目可以正常连接Oracle,但是Web项目在程序中打开Oracle连接时,系统抛出了异常:

    尝试加载 Oracle 客户端库时引发 BadImageFormatException。如果在安装 32 位 Oracle 客户端组件的情况下以 64 位模式运行,将出现此问题。

    显然,这个提示的不正确,因为我们装的就是64位的客户端,所以并不存在64位程序调用32位客户端的情况。难道是生成的程序是32位的,然后32位调用了64位的客户端,于是我把程序属性中的生成平台改为X64,如图所示:

    结果这样生成的WebService程序在调用时还是报同样的异常。这个问题困扰了我一天,其中想到的解决办法就是把64位的客户端卸载了,在X64的操作系统中安装32位的客户端,然后这样就可以了,但是如果不是Web应用(比如控制台应用程序或者WinForm程序)却同样报错,那就需要将非Web应用的项目按照上图的设置方法,将生成的平台改为X86才能正常运行。

    解决办法:

    这当然是一个折中的办法,今天终于发现了真正的原因,原来VS在建Web项目时,平时运行使用的是自带的WebDev.WebServier是一个32位的服务,所以在其中运行的Web项目不管怎么设置平台,都只能作为32位的应用来看待,所以在Web项目运行时连接64位的Oracle客户端会报错,而非Web项目就不会。

    网上搜了一下,好像WeDev服务好像没有64位的,所以要解决这个问题,那么就不要使用这个服务作为Web服务,而使用IIS,因为IIS使用的是w3wp,在64位的操作系统中是64位的,所以可以正常使用64位的Oracle客户端。具体设置如下:

     

     

    这样设置后,每次运行就好以IIS来运行,不管是Web项目还是控制台应用项目或者WinForm项目,都会正常连接Oracle了。

     

    使用VS开发基于Oracle程序的严重问题

    基于Oracle开发时遇到
         数据连接不成功,请检查该数据库是否已启动尝试加载oracle客户端时引发BadImageFormatException.如果在安装32位Oracle客户端组件的情况下以64位模式运行,将出现此问题

      The Problem in english is :
           "Attempt to load Oracle client libraries threw BadImageFormatException. This problem will occur when running in 64 bit mode with the 32 bit Oracle client components installed"  

        具体环境是:

          win2008  64

          vs 2010

            开发调试过程中都没有问题,一部署这个问题就来了。

           然后经过一大堆改动,改装64位Client之后的结果是:

            IIS测试都没有问题,一调试这个问题就来了。

           最奇怪的是这两个错误都是同样的错误信息。

           呵呵,两种情况都 让我碰到了,那就一起解决了他           

          我搞了整整两天才解决,网上有是有相关资料,但是都不全。具体原因也不明了.下面我来全面的讲述一下。

     追根究底:   

     请看下图:        

       

    VS编译器调试过程用的并不是IIS来发布   而是用上面这个进程。我们可以看到,他明显是一个32位的。而IIS 7的进程w3wp是64 bit的。这就说明,如果我们在调试,那么我们的程序就在模拟32位运行,部署之后,确是模拟64位运行,让我最不能理解的是为什么一个是模拟32位运行,一个是模拟64位运行,而给我们的异常信息确实相同的呢?先不管这么多,至少现在这里我们可以得出一个结论:

    如果你写的程序调试过程没有任何问题,那么你发布到64位IIS时就一定会有问题,反之则得到相反的结果。                      
    解决方法如下:

    情况一.调试过程没有任何问题,发布时出现问题

             若调试没有任何问题,那么你肯定是使用32 bit oracle client 了,而服务器的IIS是64 bit的,所以需要发布网站的话,必须安装64 bit client

    实际上,System.Data.OracleClient所指向的是PATH环境变量下的oci.dll。因此,我们只要让程序能够找到64位的oci.dll就可以了。方法如下:

    1. 下载instantclient-basic-win-x86-64-11.1.0.7.0.zip,并解压,如C:\instantclient-basic-win-x86-64-11.1\instantclient_11_1(这个部分也是必须的,根据实际情况的不同进行修改)。

    2. 在系统的环境变量PATH中加入以上路径。

    之后重启操作系统(这个是必须的,我弄了一下午没有搞好,结果重启一下马上就好了),程序会依照PATH路径寻找oci.dll,如果遇到32位的oci.dll会自动略过,找到64位的oci.dll就能连接上数据库了。

    情况二.调试过程出现问题,但是在IIS上测试没有问题

               若IIS测试没有任何问题,那么你肯定使用的是64 bit oracle client 了,调试出错是因为调试的WebDev进程服务器是32bit的,为了模拟真实环境,你需要进行一些设置。

    如果是这样的情况,那你就改VS的调试服务器吧,改成IIS就可以了。

     

         

           到这里,我们可以下结论,Oracle 给的异常信息对于第一种情况来说是正确的,对于第二种情况则是错误的,意思刚好相反!!!可能是做本地化人员的一个粗心错误。

          解决完这个问题之后,我的custom oracle  membership  for sharepoint的测试开发也就搞定了。近期还会记录一篇文章讲述custom oracle  membership  for sharepoint的开发总结。

     

    5 System.Data.OracleClient 需要 Oracle 客户端软件 8.1.7 或更高版本

    http://www.cnblogs.com/TerryFeng/archive/2009/02/23/1396625.html

    在用VSTS2005/2008+Oracle9做环境连接Oracle时候,在VS 开发服务器运行正常,但IIS服务器调试和部署会报错!

          IIS服务器报错:System.Data.OracleClient 需要 Oracle 客户端软件 8.1.7 或更高版本。

     

    出错的原因:

    1.虽然报的是需要安装客户端8.1.7及以上版本,实际是.net账户没有访问Oracle\bin文件夹的权限

    2.在 Windows Server 2003/2008 的 NTFS系统中提供了高级的访问安全性,FAT32系统也许没有这个问题。

     

    解决办法如下:

    我用Windows Server 2008 为例 Windows Server 2003 是一样的

    1.打开安装有Oracle客户端的电脑,在安装目录 C:\oracle\ora90\BIN 文件夹上右键-》安全选项卡-》点击  编辑---》添加。

    2.点击“查找范围”,在下面显示的账户中选择“NTWORK SERVICE”  ----将“读取和执行”的权限都赋给他(如果不行就把完全控制给他,这样不安全),子文件夹继承此权限,确定。

    3.打开“服务器管理器”-》配置-》 本地用户和组-》组-》adminisgrators-》将Network Service 添加进来

    4.重新启动IIS,在“运行”中输入“IISRESET”。

     

     

    转载于:https://www.cnblogs.com/sqlite3/archive/2012/05/24/2566692.html

    展开全文
  • c++之指针和引用

    2020-10-11 19:23:17
    关于指针的运算2、指针数组3、常量与指针普通指针常量指针指针常量常量指针常量4、指针与类1、访问类成员2、在堆中创建对象四、引用1、什么是引用2、 把引用作为返回值3、常量和引用4、引用传参指针传参五、指针...


    一、什么是指针

    首先先了解什么是内存地址:对程序进行编译时,系统就会为这个变量分配内存单元。编译系统根据程序中定义的变量类型分配一定长度的空间,内存的基本单元是字节,一字节有8位,内存是以字节为单位的连续编址空间, 每一个字节单元对应着一个唯一的编号, 这个编号被称为内存单元的地址
    而指针:
    1、指针是存储对象的内存地址的一个特殊变量
    2、每个内存地址是可以存放一些数据的。这些数据就叫做“指针所指的数据”或者“指针指向的数据”
    3、其主要有三个目的:

    1. 在堆上分配新对象,
    2. 将函数传递给其他函数
    3. 迭代数组或其他数据结构中的元素

    二、指针的作用

    一、指针就是指向一个特定内存地址的一个变量。C\C++中指针可以有效地表示复杂的数据结构、动态分配内存、高效地使用数组和字符串、使得调用函数时得到多个返回值等。
    二、指针使得不同区域的代码可以轻易的共享内存数据。
    三、指针使得一些复杂的链接性的数据结构的构建成为可能。
    四、在使用new等操作时,必须使用到内存,可以更高效的处理内存

    二、指针的使用

    在使用指针前必须对指针进行声明

    //声明格式 type *var-name;
    int   a= 20;   
    int* b;        // 指针变量的声明
    
    b = &a;       // 存储 a 的地址
    
    

    我们使用vs来调试下
    在这里插入图片描述

    “*”的作用是按照指向关系访问所指向的对象的值

    从中可以得出:
    1、指针也是存在地址的
    2、指向的值,也就是指向对象的地址

    1.关于指针的运算

    这里的var并不是数组本身

    int  var[6] = { 1,2,3,4,5,6 };
    	int* ptr;
    	//int* ptr = &a 初始化指针
    	
    	// 指针中的数组地址
    	ptr = var; 
    	for (int i = 0; i < 6; i++)
    	{
    		cout << "ptr=[" << i << "]";
    		cout << ptr << endl;
    
    		cout << "*ptr[" << i << "] = ";
    		cout << *ptr << endl;
    
    		// 指针向下一个进行移动
    		ptr++;
    	}
    

    结果很正确,一个int占用4个字节
    在这里插入图片描述

    2、指针数组

    int  var[6] = { 1,2,3,4,5,6 };
    	int* ptr[6];
    	for (int i = 0; i < 6; i++)
    	{
    		ptr[i] = &var[i]; // 赋值为整数的地址
    		cout << "var[" << i << "]=" << *ptr[i] << endl;
    	}
    	return 0;
    

    结果依然和预期的一样,我们接下来调试一下
    在这里插入图片描述
    每次运行到 ptr[i] = &var[i] 时,赋予指针一个元素
    在这里插入图片描述

    3、常量与指针

    常量就是不可变的数据
    常量指针:指向常量的指针,在指针定义语句的类型前加const,表示指向的对象是常量。

    先看如下代码`,这里调试可能会出现不必要的问题

    普通指针

    int a = 5,z=0;
    int* ra = &a; //整型指针 指向a的地址
    a = a + 1;
    cout << ra << endl;//00D5FB54
    ra = &z; // 改变指针的地址
    cout << ra << endl;`//00D5FB48
    

    结论:指针指向的地址是可以改变的

    常量指针

    const int b =6;
    int* rb = &b;
    //error C2440: “初始化”: 无法从“const int *”转换为“int *”
    

    编译器报错,原因: 因为b是一个常量,所以 &b也不能被改变,所以rb指向的值也不可以被改变

    const int b =6;
    const int* rb = &b; //常量指针
    *rb = a; //error “rb”: 不能给常量赋值
    

    在看

    cout << *rb<<endl;  //6
    rb = &z; //但是可以改变指针本身
    cout << *rb; //0
    

    结论:指针指向的值不能被改变,指针本身的值可以被改变

    指针常量

    int x = 7;
    int* const rx = &x; // 指针常量
    
    int z =0;
    rx = &z;// error C3892: “rx”: 不能给常量赋值
    (*rx) = z; //正常
    

    运行如下
    在这里插入图片描述
    结论:不能给常量赋值,可以改变指针指向的值,与常量指针相反

    常量指针常量

    const int c = 5;
    const int* const rc = &c;
    rc = 100; 
    rc = &z;
    *rc = &z;
    

    在这里插入图片描述
    全报错,结论:不能改变指向的值,本身也不能被改变

    • (指针)和 const(常量) 谁在前先读谁 ;* 代表被指的数据,名字代表指针地址

    const在谁前面谁就不允许改变。

    4、指针与类

    1、访问类成员

    我们先定义一个类

    class Circle {
    public://设为公有
        double radius;
        Circle() {
            radius = 1;
        }
        Circle(double newRadius) {
            radius = newRadius;
        }
        double getArea() {
            return radius * radius * 3.14159;
        }
    };
    

    箭头运算符 -> :用指针访问对象成员 就不用直接加*号了

     Circle circle1;
        Circle* pCircle = &circle1;
        cout << "The radius is " << (*pCircle).radius << endl;
        cout << "The area is " << (*pCircle).getArea() << endl;
        (*pCircle).radius = 5.5;
        cout << "The radius is " << pCircle->radius << endl;
        cout << "The area is " << pCircle->getArea() << endl;
    

    运行如下
    在这里插入图片描述

    2、在堆中创建对象

    在函数中声明的对象都在栈上创建,函数返回,则对象被销毁
    你可以用new运算符在堆上创建它,为保留对象

    new Circle{}
    如果请求的存储空间为零字节,则 operator new 返回指向不同对象的指针。 也就是说,重复调用将
    operator new 返回不同的指针。 如果分配请求没有足够的内存,则会 operator new 引发 std::bad_alloc
    异常。 或者, nullptr 如果已在非引发支持中链接,则返回 operator new 。
    delete
    使用运算符动态分配的内存 new 可以使用运算符来释放 delete 。 Delete 运算符调用 operator delete 函数,该函数将内存释放回可用池。 使用 delete 运算符还会导致调用类析构函数(如果存在)。

    Circle *pCircle1 = new Circle{}; //用无参构造函数创建对象
    
    Circle *pCircle2 = new Circle{5.9}; //用有参构造函数创建对象
    
    //程序结束时,动态对象会被销毁,或者
    
    delete pObject;  //用delete显式销毁
    

    四、引用

    1、什么是引用

    引用变量是一个别名,它它是某个已存在变量的另一个名字。一旦把引用初始化为某个变量,就可以使用该引用名称或变量名称来指向变量。

    int i = 10;
    int& ref = i; //ref引用了i
    ref++;
    

    下面这是错误的写法,引用必须初始化,不存在空引用

    int i = 10;
    int& ref ;
    ref = i;
    ref++;
    

    内存地址相同,对ref的操作会作用到i上
    在这里插入图片描述

    2、 把引用作为返回值

    double vals[] = { 10.1, 12.6, 33.1, 24.1, 50.0 };
    
    double& setValues(int i)
    {
        return vals[i];   // 返回第 i 个元素的引用
    }
    

    其结果为
    在这里插入图片描述

    3、常量和引用

    const char* t = "word";
    const char* s = "Hello";
    const char*& rs = s;
    std::cout << s << std::endl;
    rs = t;//rs引用被重新赋值为t
    std::cout << rs << std::endl;
    

    在这里插入图片描述

    4、引用传参和指针传参

    二、引用参数
    一下两穿代码作用相同
    指针,交换的是地址

    void swap(int *a,int *b)
    {
    int temp;
    temp=*a;
    a=*b;
    *b=temp;
    }
    

    引用传参,交换的是实参

    void swap(int &a,int &b)
    {
    int temp;
    temp=a;
    a=b;
    b=temp;
    }
    
    int main() {
    	int a = 1, b = 42;
    	swap(a, b);//引用传参,实参
    	swap(&a, &b); //指针传参,地址
    	return 0;
    }
    

    当大型对象被传递给函数时,使用引用参数可使参数传递效率得到提高,因为引用并不产生对象的
    副本,也就是参数传递时,对象无须复制

    五、指针和引用的区别

    1、引用不可以为空,但指针可以为空。定义一个引用的时候,必须初始化。指针随意
    2、引用不可以改变指向,但是指针可以改变指向。虽然引用不可以改变指向,但是可以改变初始化对象的值,而对指针的操作,会使指针指向其他对象
    3、引用的大小是所指向的变量的大小,因为引用只是一个别名而已,内存地址和对象相同;指针是指针本身的大小,4个字节,本身就存在一个内存地址中
    4、引用比指针更安全。由于不存在空引用,并且引用一旦被初始化为指向一个对象,它就不能被改变为另一个对象的引用。对于指针来说,它可以随时指向别的对象,并且可以不被初始化,或为NULL。const
    指针虽然不能改变指向,但仍然存在空指针,并且有可能产生野指针(即多个指针指向一块内存,free掉一个指针之后,别的指针就成了野指针)。
    5、“sizeof 引用”得到的是所指向的变量(对象)的大小,而“sizeof 指针”得到的是指针本身的大小;
    6、指针和引用的自增(++)运算意义不一样;

    指针传递和引用传递

    转载:C++中引用和指针的区别
    这位大佬写的挺不错的

    1、指针传递参数本质上是值传递的方式,它所传递的是一个地址值。值传递过程中,被调函数的形式参数作为被调函数的局部变量处理,即在栈中开辟了内存空间以存放由主调函数放进来的实参的值,从而成为了实参的一个副本。值传递的特点是被调函数对形式参数的任何操作都是作为局部变量进行,不会影响主调函数的实参变量的值。
    2、引用传递过程中,被调函数的形式参数也作为局部变量在栈中开辟了内存空间,但是这时存放的是由主调函数放进来的实参变量的地址。被调函数对形参的任何操作都被处理成间接寻址,即通过栈中存放的地址访问主调函数中的实参变量。正因为如此,被调函数对形参做的任何操作都影响了主调函数中的实参变量。

    引用传递和指针传递是不同的,虽然它们都是在被调函数栈空间上的一个局部变量,但是任何对于引用参数的处理都会通过一个间接寻址的方式操作到主调函数中的相关变量。而对于指针传递的参数,如果改变被调函数中的指针地址,它将影响不到主调函数的相关变量。如果想通过指针参数传递来改变主调函数中的相关变量,那就得使用指向指针的指针,或者指针引用。

    从概念上讲。指针从本质上讲就是存放变量地址的一个变量,在逻辑上是独立的,它可以被改变,包括其所指向的地址的改变和其指向的地址中所存放的数据的改变。

    而引用是一个别名,它在逻辑上不是独立的,它的存在具有依附性,所以引用必须在一开始就被初始化,而且其引用的对象在其整个生命周期中是不能被改变的(自始至终只能依附于同一个变量)。

    在C++中,指针和引用经常用于函数的参数传递,然而,指针传递参数和引用传递参数是有本质上的不同的:

    总结

    提示:这里对文章进行总结:
    相同点:

    都是地址的概念;

    指针指向一块内存,它的内容是所指内存的地址;而引用则是某块内存的别名。

    不同点:

    1、引用不可以为空,但指针可以为空。定义一个引用的时候,必须初始化。指针随意
    2、引用不可以改变指向,但是指针可以改变指向。虽然引用不可以改变指向,但是可以改变初始化对象的值,而对指针的操作,会使指针指向其他对象
    3、引用的大小是所指向的变量的大小,因为引用只是一个别名而已,内存地址和对象相同;指针是指针本身的大小,4个字节,本身就存在一个内存地址中
    4、引用比指针更安全。由于不存在空引用,并且引用一旦被初始化为指向一个对象,它就不能被改变为另一个对象的引用。对于指针来说,它可以随时指向别的对象,并且可以不被初始化,或为NULL。const
    指针虽然不能改变指向,但仍然存在空指针,并且有可能产生野指针(即多个指针指向一块内存,free掉一个指针之后,别的指针就成了野指针)。
    5、“sizeof 引用”得到的是所指向的变量(对象)的大小,而“sizeof 指针”得到的是指针本身的大小;
    6、指针和引用的自增(++)运算意义不一样;

    参考–微软官文档
    csdn-Listening_music

    展开全文
  • 一、原始值和引用值的概念 在 ECMAScript 中,变量可以存在两种类型的值,即原始值和引用值。 1.1 原始值 ...(2)存储在栈(stack)中的简单数据段,也就是说,它们的值直接存储在变量访问...
        

    一、原始值和引用值的概念

    在 ECMAScript 中,变量可以存在两种类型的值,即原始值引用值

    1.1 原始值

    (1)原始值指的是 原始类型 的值,也叫 基本类型,例如 Number、Stirng、Boolean、Null、Underfined 。

    (2)存储在栈(stack)中的简单数据段,也就是说,它们的值直接存储在变量访问的位置

    (3)注意

    在许多语言中,字符串都被看作引用类型,而非原始类型,因为字符串的长度是可变的。ECMAScript 打破了这一传统。

    1.2 引用值

    (1)引用值指的是 引用类型 的值,例如 Object、Function、Array、Date、RegExp 。

    (2)存储在堆(heap)中的对象,也就是说,存储在变量处的值是一个指针(point),指向存储对象的内存处

    二、栈和堆

    2.1 原始值存储在栈中

    为变量赋值时,ECMAScript 的解释程序必须判断该值是原始类型,还是引用类型。要实现这一点,解释程序则需尝试判断该值是否为 ECMAScript 的原始类型之一,即 Undefined、Null、Boolean、Number 和 String 型。由于这些原始类型占据的空间是固定的,所以可将他们存储在较小的内存区域 - 栈中。这样存储便于迅速查寻变量的值。

    2.2 引用值存储在堆中

    如果一个值是引用类型的,那么它的存储空间将从堆中分配。由于引用值的大小会改变,所以不能把它放在栈中,否则会降低变量查寻的速度。相反,放在变量的栈空间中的值是该对象存储在堆中的地址。地址的大小是固定的,所以把它存储在栈中对变量性能无任何负面影响。

    2.3 图示

    栈中的原始值与堆中的引用值

    三、原始值和引用值的不同

    3.1 赋值方式

    3.2 值是否可变

    3.3 比较方式不同

    四、赋值方式和值是否可变

    4.1 原始值是以值的拷贝方式赋值,值是不可变的

    4.2 引用值是以引用的拷贝方式赋值,值是可变的

    4.3 Example

    Example

    4.4 说明

    (1)原始值赋值 → 其实是将值拷贝一份并赋值给新的变量,这个值就是副本,他和原始值是互相独立的,改变其中一个值不会影响到其他的值。

    (2)引用值赋值 → 当一个引用类型,例如一个对象,使用 = 将其赋值给另一个变量,实际上是其对象的地址引用赋值给新的变量,这两个变量都指向同一个地址引用,他们有相同的地址。所以若改变其中一个变量(的地址引用指向的对象),另一个变量(的地址引用指向的同一个对象)也将改变。

    图示

    4.5 扩展

    Example

    五、比较方式不同

    5.1 原始值的比较是 的比较

    5.2 引用值的比较是 引用 的比较

    5.3 Example

    Example

    5.4 说明

    (1)原始值 a 和 b 的数据类型不同,但也可以进行值的比较。(在值比较之前,自动进行了数据类型的 隐式转换

    • == → 只比较值
    • === → 不仅比较值,还比较数据类型

    (2)引用值 obj1 和 obj2 分别引用的是存放在堆内存中的两个不同的对象,所以 obj1 和 obj2 的值(地址引用)不一样。

    阅读更多

    展开全文
  • 句柄是一种特殊的智能指针 。当一个应用程序要引用其他系统(如数据库、...这种间接访问对象的模式增强了系统对引用对象的控制。句柄就是个数字,一般当前系统下的整数的位数一样,比如32bit系统下就是4个字节。 ...

    句柄是一种特殊的智能指针 。当一个应用程序要引用其他系统(如数据库、操作系统)所管理的内存块或对象时,就要使用句柄。

    句柄与普通指针的区别在于,指针包含的是引用对象的内存地址,而句柄则是由系统所管理的引用标识,该标识可以被系统重新定位到一个内存地址上。这种间接访问对象的模式增强了系统对引用对象的控制。

    句柄就是个数字,一般和当前系统下的整数的位数一样,比如32bit系统下就是4个字节。

    ce3b46a0431197067c24d12e54762078.png

           
    这个数字是一个对象的唯一标示,和对象一一对应。       
    这个对象可以是一个块内存,一个资源,或者一个服务的context(如 socket,thread)等等。     

     
    这个数字的来源可以有很多中,只要能保证和它代表的对象保持唯一对应就可以,比如可以用内存地址,也可以用句柄表的序号,或者干脆用一个自增ID,再或者用以上的值去异或一个常数。

    传统上操作系统内核和系统服务API都是 C 语言接口的,但是其内部设计理念上又是OO的,所以有对象概念却没有对应的语言语法支持。     

     句柄的作用就是在 C 语言环境下代替 C++ 的对象指针来用的。       
    创建句柄就是构造,销毁句柄就是析构,用句柄调用函数相当于传入this指针。       
    如果有系统API是 C++ 接口的,那么就没有句柄了,而是某个接口指针,IXXXPtr之类的,比如Windows的com ptr。

    句柄和指针的区别

    当把硬盘上的资源调入内存以后,将有一个句柄指向它,但是句柄只能指向一个资源。而且句柄知道所指的内存有多大。还有指针,指针指向地址,它不知道分配的内存有多大。

    句柄是一个32位的整数,实际上是windows在内存中维护的一个对象(窗口等)内存物理地址列表的整数索引。因为windows的内存管理经常会将当前空闲对象的内存释放掉,当需要时访问再重新提交到物理存储,所以对象的物理地址是变化的,不允许程序直接通过物理地址来访问对象。

    程序将想访问的对象的句柄传递给系统,系统根据句柄检索自己维护的对象列表就能知道程序想访问的对象及其物理地址了。句柄是一种指向指针的指针。我们知道,所谓指针是一种内存地址。

    应用程序启动后,组成这个程序的各个对象是驻留在内存的。如果简单地理解,似乎我们只要获知这个内存的首地址,那么就可以随时用这个地址访问对象了。

    但是,如果真这么认为,那么就大错特错了。我们知道windows是一个虚拟内存为基础的操作系统。

    在这种情况下,windows内存管理器经常在内存中来回移动对象,以此来满足各种应用程序的内存需要,对象被移动意味着它的地址变化了。如果地址总是如此的变化,我们应该去那里找对象呢?为了解决这个问题,windows操作系统为各个应用程序腾出一些内存地址,用来专门登记各个应用对象在内存中的地址变化,而这个地址(存储单元的位置)本身是不变的。

    windows内存管理器移动对象在内存中的位置后,把对象新的地址告知这个句柄地址来保存。这样我们只需要记住这个句柄地址就可以间接地知道对象具体在内存中哪个位置了。

    这个地址是在对象装载(load)时由系统分配的,当系统卸载时又释放给系统。句柄地址(稳定)—–>记载着对象在内存中的地址——–>对象在内存中的地址(不稳定)—–>实际对象。但是必须注意,程序每次重新启动,系统不保证分配跟这个程序的句柄还是原来哪个句柄,而绝大多数情况下的确不一样。假如我们把进入电影院看电影看成是一个应用程序的启动运行,那么系统给应用程序分配的句柄总是不一样,这和每次电影院给我们的门票总是不同的座位是一个道理。

    因此,句柄和指针其实是两个截然不同的概念。windows系统用句柄标记系统资源,用句柄隐藏系统信息。你只需要知道有这个东西,然后去调用它就行了,它是32bit的uint。指针则标记某个物理内存的地址,是不同的概念。

    指针对应着一个数据在内存中的地址,得到了指针就可以自由地修改该数据。Windows并不希望一般程序修改其内部数据结构,因为这样太不安全。所以Windows给每个使用GlobalAlloc等函数声明的内存区域指定一个句柄(本质上仍是一个指针,但不要直接操作它),平时你只是在调用API函数时利用这个句柄来说明要操作哪段内存。当你需要对某个内存进行直接操作时,可以使用GlobalLock锁住这段内存并获得指针来直接进行操作。

    句柄是指针的“指针”,使用句柄主要是为了利于windows在进程内存地址空间移动分配的内存块,以防止进程的内存空间被撕的四分五裂而存在过多的碎片。

    句柄是一些表的索引也就是指向指针的指针。间接的引用对象,windows可以修改对象的”物理”地址和?描述器的值,但是句柄的值是不变的。

    句柄可以在获得窗口的时候使用,指针可以进行调用窗口,两个使用的地方不一样.一个括号外,一个括号内.

    隐喻

    CSDN上有人说过:牧童遥指杏花村。       
    牧童的手为指针,杏花村的牌子为句柄,杏花村酒店为对象的实例.        
    句柄是资源在创建过程中由Windows赋予的,它就是代表这个资源的。

    而指针实质上是某个变量或者对象所在内存位置的首地址,是指向对象的。

    一个是指向,一个是代表,二者是不同的。

    一个是直接找到对象(指针),一个是间接找到对象(句柄)。

    例如,杏花村可以搬家(实际上程序运行过程中,资源在内存中的地址是变化的),那么牧童的手的指向也就不同(指针)了,然而即使搬了家,“杏花村”这块牌匾是不变的,通过打听“杏花村”这个名称,还是可以间接找到它的(地址)。

    HANDLE的本意是把柄,把手的意思,是你与操作系统打交道的东东。

    指针与引用

    (1) 指针是对象在内存中的地址;

    (2) 引用是对象的别名,其实质就是功能受限但是安全性更高的指针;

    (3) 句柄是指针的指针,句柄实际上是一个数据,是一个Long (整长型)的数据。句柄是一个标识符,是拿来标识对象或者项目的,它就象我们的姓名一样。Windows是一个以虚拟内存为基础的操作系统。

    在这种系统环境下,Windows内存管理器经常在内存中来回移动对象,依此来满足各种应用程序的内存需要。对象被移动意味着它的地址变化了。如果地址总是如此变化,我们该到哪里去找该对象呢?为了解决这个问题,Windows操作系统为各应用程序腾出一些内存储地址,用来专门登记各应用对象在内存中的地址变化,而这个地址(存储单元的位置)本身是不变的。

    Windows内存管理器在移动对象在内存中的位置后,把对象新的地址告知这个句柄地址来保存。

    引用与指针的区别

    常常有人问引用与指针的区别,可能是指针和引用在功能上的相似,而是他们混淆这两个概念, 现在总结以下二者的区别,希望大家能彻底弄清这两个概念根本性的差别:

    引用,一个变量的别名,为什么引入别名呢?原因是我们想定义一个变量,他共享另一个变量的 内存空间,使用别名无疑是一个好的选择。变量是什么?是一个内存空间的名字,如果我们给这个 内存空间在起另外一个名字,那就是能够共享这个内存了,引用(别名)的由此而来。

    指针,指向另一个内存空间的变量,我们可以通过它来索引另一个内存空间的内容,本身有自己的 内存空间。

    二者区别:

    • 引用访问一个变量是直接访问,而指针是间接访问。

    • 引用是一个变量的别名,本身不单独分配自己的内存空间,而指针有自己的内存空间。

    • 引用在开始的时候就绑定到了一个内存空间(开始必须赋初值),所以他只能是这个 内存空间的名字,而不能改成其他的,当然可以改变这个内存空间的值.

    http://www.360doc.com/content/14/0120/15/7591436_346648771.shtml

    (1)指针是对象在内存中的地址;

    (2)引用是对象的别名,其实质就是功能受限但是安全性更高的指针;

    (3)句柄是指针的指针,句柄实际上是一个数据,是一个Long (整长型)的数据。句柄是一个标识符,是拿来标识对象或者项目的,它就象我们的姓名一样。Windows是一个以虚拟内存为基础的操作系统。在这种系统环境下,Windows内存管理器经常在内存中来回移动对象,依此来满足各种应用程序的内存需要。

    对象被移动意味着它的地址变化了。如果地址总是如此变化,我们该到哪里去找该对象呢?为了解决这个问题,Windows操作系统为各应用程序腾出一些内存储地址,用来专门登记各应用对象在内存中的地址变化,而这个地址(存储单元的位置)本身是不变的。

    Windows内存管理器在移动对象在内存中的位置后,把对象新的地址告知这个句柄地址来保存。

    Java中有3个数据类型:基本数据类型、引用类型和null类型。其中,引用类型包括类类型(含数组)、接口类型。

    为了区别引用类型的变量标识符和基本数据类型变量标识符,我们特别的(特意的)使用Handle来称呼引用类型的变量标识符。对象的引用是创建对象时的返回值!引用是new表达式的返回值。

    new A(); 这里真正创建了一个对象,但我们没有用句柄去持有(hold、拿着、保存)该引用。handle是变量,reference是一种变量值。

    - EOF -

    推荐阅读  点击标题可跳转

    java精品入门-0基础第一篇

    JDK、JRE、JVM的区别与联系

    变量与数据类型 java基础03

    运算符-小学生都能学会的java基础

    java循环经典案例-学会它入行java

    java基础之方法重载

    java数组精讲-多案例-够详细

    java中基本类型包装类

    都来到这了,我需要你的点赞支持 

    展开全文
  • 数组的定义和访问

    2020-08-22 14:35:19
    假设该公司有500名员工,用前面学的知识,程序员首先需要声明500个变量分别存储每员工的工资,然后在进行操作,这样做会很麻烦的,而且错误率也会很高,因此我们可以使用数组(容器)进行操作,将所有的数据全部存储...
  • 数组是相同元素的集合,它的每个元素是通过下标引用或指针间接访问来选择的。结构也是一些值的集合,这些值称之为它的成员,但一个结构的各个成员可能具有不同的类型。数组元素可以通过下表访问,因为数组元素的元素...
  • 在 JAVA 程序运行时,对象是存储在堆内存(Heap)中的,C/C++ 中是通过指针来访问所谓对象(结构体)的,而 JAVA 则是通过引用访问对象,也就是说,引用指向了对象在堆内存中的地址,引用本身也占用内存,64 的 ...
  • C++ 的内存管理机制 C++ 内存分配方式,五个区:堆区、栈区、自由存储区、全局/静态存储区、常量存储区。 不能访问未申请、未初始化的内存、申请失败的内存或者已经释放的...64 系统下除了指针类型 long long ...
  • 51 单片机开发中经常会引用一个 reg51.h 的头文件,看看他是如何把名字寄存器联系起来的:sfr P0 =0x80;sfr 也是一种扩充 数据类型,点用一个 内存单元,值域为 0~255。利用它可以访问 51单片机内部的所有特殊...
  • 如果要使用32位引用,则您的堆数量限制为32 GB。但是,如果您愿意使用64位引用,则大小可能受您的操作系统...如果您的JVM跨越NUMA区域,内存访问和GC特别需要更长的时间。如果您的JVM堆开始交换,则GC可能需要几个小...
  • 进程对文件的访问权限应用模型:进程的属主与文件的属主是否相同。如果相同,则应用属主权限;否则去检查金证的属于是否属于文件的属组;如果是,则应用属组权限,否则,就只能引用other权限。 权限:r:readable,...
  • 一、变量的地址计算机中,数据存储在...变量的访问方式:直接访问,间接访问3.指针变量:是存放地址的变量二、指针变量的定义与引用1.定义方法:类型符 *指针变量名指针变量的类型 所指向的内存中存放的数据的类型...
  • ArrayList数组 物理结构连续,并且有自己的下标,因而访问起来效率高,但也因其物理结构连续,插入元素时插入位置后的元素都要后移一,删除同理,故而添加/删除元素的效率不高 LinkedList双向链表,列表中的每个节点都...
  • 但是,因为在大多数C++环境中,没有元素类型是单个,所以各个访问元素为特殊引用类型。 集合可以从整数值二进制字符串构造,并转换为整数值二进制字符串;也可以以二进制格式直接从流中提取。
  • *空指针用于给指针变量进行初始化,不可以进行访问 int p=NULL; #include<iostream> using namespace std; int mian() { //1.定义指针 int a = 10; //整型变量 int *p; //int *p = &am
  • 基本数据类型是指存放在栈中的简单数据段,数据大小确定,内存空间大小可以分配,它们是直接按值存放的,所以可以直接按值访问! (int a = 10; int b = a; int b = 20;) 将一个基本数据类型赋值给另外一个,栈...
  • 数组是相同类型元素的集合,它的每个元素是通过下标引用或指针间接访问来选择的。结构也是一些值的集合,这些值成为它的成员,但一个结构的各个成员可能具有不同的类型。每个结构成员都有自己的名字,它们是通过名字...
  • 第一步:下载DLL; ... 第二步:在程序中引用Oracle.ManagedDataAccess.dll,删除之前...64位 Oracle.ManagedDataAccess.dll同时支持32位和64位winform程序; 下载12.2c版本的Oracle.ManagedDataAccess.dll可以访问..
  • 数组是相同类型元素的集合,它的每个元素是通过下标引用或指针间接访问来选择的。结构也是一些值的集合,这些值成为它的成员,但一个结构的各个成员可能具有不同的类型。每个结构成员都有自己的名字,它们是通过名字...
  • 对象的访问定位

    2016-03-24 16:14:05
    建立对象是为了使用对象,我们的...访问堆中的对象的具体位置,所以对象访问方式也是取决于虚拟机实现而定的。目前主流的访问方式有使用句 柄直接指针两种。 如果使用句柄访问的话,那么Java堆中将会划分出一块
  • 结构体c语言提供了两种聚合数据类型,分别为数组指针,数组是相同类型元素的集合,它的每个元素是通过下标引用或指针间接访问的。结构是不同数据类型的集合,对于结构的访问不能通过下标去访问,因为一个结构的...
  • 数组里面保存的是同类型的元素的集合,它的每个元素是通过下标引用或者指针间接访问来选择的。 结构也是一些值的集合,这些值称为它的成员,但一个结构的各个成员可能具有不同的类型,他们需要通过名字去访问,那个...
  • jvm之对象的访问定位

    2017-09-02 18:17:32
    建立对象是为了使用对象,...访问堆中的对象的具体位置,所以对象访问方式也是取决于虚拟机实现而定的。目前主流的访问方式有使用句 柄直接指针两种。 如果使用句柄访问的话,那么Java堆中将会划分出一块...
  • 1、数组:数组是相同类型的元素的集合,它的每个元素是通过下标引用或者指针间接访问来选择的。 2、结构体:结构体也是一些值的集合,这些值称为它的成员,但是一个结构体的各个成员可能具有不同的类型。 3、数组...
  • 为了有效地完成数据存储任务,需要对存储器做如下处理:1 划分:以字节(8个bit,对应8个开关晶体管,0或1)为单位将存储器划分为一系列的存储单元。2 编址:以线性方式给每个存储单元赋予唯一的存储地址,可以随机...
  • public表示任何人都可以访问同一程序集中的任何其他代码或引用该程序集的其他程序集都可以访问该类型或成员。 注:将一个类或类成员标志public时,任何其他类的任何实例可以访问它。这是限制最弱的的访问修饰符。...
  • 能使用的内存大小CPU位数有关,在32的CPU上,能用的内存大小是4G,在64CPU上,是2^64。(这里不区分虚拟物理)二、分配流程先了解内存分配的大概流程:用户进程使用malloc接口分配虚拟内存用户进程访问内存...
  • 参考链接:STM32F0非对齐访问引起的硬件错误及其...代码一代码二的功能其实是一样的,都是在指定的faddr地址中取两个字节的数据形成一个16的无符号整型数据,乍一看这是符合语法规则的,在F1系列的板子上代码都可
  • 先继续干活吧,等一会数据调通了,根据那同学的建议把那些工具类的代码新建一个项目,生成dll,然后在主项目里引用它试试。 ## * 补充5: 我还是不理解,在同项目中,多个类引用同一个类中的枚举类型,为什么...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 523
精华内容 209
关键字:

引用位和访问位