精华内容
下载资源
问答
  • 数组本身的标识是占地方的,把数组第一个元素的地址作为数组的标识。所以这个问题有趣的地方在这里。 编译时 B里面编译器认为a是指针,所有它认定这个指针在某个地方占了一个int长。B里面编译器...

    思科的一道面试题如下:

    不要用编译器  用1分钟事件思考下

    源文件A:
    int a[10];
    int *b=a;

    源文件B:
    extern int *a;
    extern int b[];
    int x,y;
    ...
    x=a[3];
    y=b[3];

    解释执行两条赋值语句时会发生什么?


    ChinaUnix里面有一高人的解释如下:

    这个问题不会产生编译错误和链接错误,也就是说程序是合法的。当然运行时是会出问题的。指针本身的标识需要占用一个int长的空间;数组本身的标识是不占地方的,把数组第一个元素的地址作为数组的标识。所以这个问题有趣的地方在这里。


    编译时

    B里面编译器认为a是指针,所有它认定这个指针在某个地方占了一个int长。B里面编译器认为b是数组,所有它认定这个数组的地址是某个地方的第一个元素地址。

    A里面编译器认为a是数组,b是指针,这是很直接的。


    链接时

    缺的都是符号,刚好有,所有连上去了B(a)=A(a),B(b)=A(b)


    运行时

    因为B(a)被认为是指针,所以运行的时候那个地址应该是一个int长来存放它的内容,所以它把A(a)的第一个int长作为指针的空间,所以A(a)的第一个数组元素的值就做了指针的值。
    因为B(b)被认为是数组,所以运行的时候那个地址应该是一个数组的首元素地址,所以B(b)的第一个元素应该保存的是a的地址。

    也就是说,如果A(a) = {n,......};,那么B(a)=n,B(b)=&A(a)


    链接之后,b[3]是随机的,但是b[0]=&a和a=n是确定的。


    讨论参见http://bbs.chinaunix.net/thread-3705891-1-1.html

    展开全文
  • 引用和常量引用

    千次阅读 2017-07-02 20:28:24
    在实际程序中,引用主要用作函数的形式参数。在这里,我们用独立的对象来介绍并举例说明引用的用法。引用是一种复合类型(compound type),通过在变量名前添加“&”符号来定义。复合类型是指用其他类型定义的类型...

    引用(reference)用作对象的另一名字。在实际程序中,引用主要用作函数的形式参数。在这里,我们用独立的对象来介绍并举例说明引用的用法。

    引用是一种复合类型(compound type),通过在变量名前添加“&”符号来定义。复合类型是指用其他类型定义的类型。在引用的情况下,每一种引用类型都“关联到”某一其他类型。不能定义引用类型的引用,但可以定义任何其他类型的引用。

    引用必须用和该引用同类型的对象初始化:

    int ival = 1024;
    
    int &refVal = ival; // ok: refVal refers to ival
    
    int &refVal2; // error: a reference must be initialized
    
    int &refVal3 = 10; // error: initializer must be an object
    1. 引用是别名

    因为引用只是它绑定的对象的另一名字,作用在引用上的所有操作事实上都是作用在该引用绑定的对象上:

    refVal += 2;

    将refVal指向的对象ival加2。类似地,

    int ii = refVal;

    把和ival相关联的值赋给ii。

    当引用初始化后,只要该引用存在,它就保持绑定到初始化时指向的对象。不可能将引用绑定到另一个对象。

    要理解的重要概念是引用只是对象的另一名字。事实上,我们可以通过ival的原名访问ival,也可以通过它的别名refVal访问。赋值只是另外一种操作,因此当我们编写

    refVal = 5;

    效果是把ival的值修改为5。这一规则的结果是必须在定义引用时进行初始化。初始化是指明引用指向哪个对象的唯一方法。

    1. 定义多个引用

    可以在一个类型定义行中定义多个引用。必须在每个引用标识符前添加“&”符号:

    int i = 1024, i2 = 2048;
    
    int &r = i, r2 = i2; // r is a reference, r2 is an int
    
    int i3 = 1024, &ri = i3; // defines one object, and one reference
    
    int &r3 = i3, &r4 = i2; // defines two references
    1. const引用
    const引用是指向const对象的引用:
    
    const int ival = 1024;
    
    const int &refVal = ival; // ok: both reference and object are const
    
    int &ref2 = ival; // error: nonconst reference to a const object

    可以读取但不能修改refVal,因此,任何对refVal的赋值都是不合法的。这个限制有其意义:不能直接对ival赋值,因此不能通过使用refVal来修改ival。

    同理,用ival初始化ref2也是不合法的:ref2是普通的非const引用(nonconst reference),因此可以用来修改ref2指向的对象的值。通过ref2对ival赋值会导致修改const对象的值。为阻止这样的修改,须要规定将普通的引用绑定到const对象是不合法的。

    术语:const引用是指向const的引用

    C++程序员常常随意地使用术语const引用。严格来说,“const引用”的意思是“指向const对象的引用”。类似地,程序员使用术语“非const引用”表示指向非const类型的引用。这种用法非常普遍,我们在本书中也遵循这种用法。

    const引用可以初始化为不同类型的对象或者初始化为右值(2.3.1节),如字面值常量:

    int i = 42;
    
    // legal for const references only
    
    const int &r = 42;
    
    const int &r2 = r + i;

    同样的初始化对于非const引用却是不合法的,而且会导致编译时错误。其原因非常微妙,值得解释一下。

    观察将引用绑定到不同的类型时所发生的事情,最容易理解上述行为。假如我们编写

    double dval = 3.14;
    
    const int &ri = dval;

    编译器会把这些代码转换成如以下形式的编码:

    int temp = dval; // create temporary int from the double
    
    const int &ri = temp; // bind ri to that temporary

    如果ri不是const,那么可以给ri赋一新值。这样做不会修改dval,而是修改了temp。期望对ri的赋值会修改dval的程序员会发现dval并没有被修改。仅允许const引用绑定到需要临时使用的值完全避免了这个问题,因为const引用是只读的。

    非const引用只能绑定到与该引用同类型的对象。

    const引用则可以绑定到不同但相关的类型的对象或绑定到左值。

    展开全文
  • Google C++ Coding Style:引用参数

    千次阅读 2015-07-29 00:43:55
    Google C++ Coding Style定义输入参数以值或者const引用形式传入,输出参数使用指针。 所有以引用形式输入参数必须加上const,即const T&的形式。即如下形式:void Foo(const string &in, string *out);在如下情况下,...

    Google C++ Coding Style定义

    输入参数以值或者const引用形式传入,输出参数使用指针。 所有以引用形式输入参数必须加上const,即const T&的形式。

    即如下形式:

    void Foo(const string &in, string *out);

    在如下情况下, 可以使用const T*的形式:
    * 需要进行指针的判空 (即空指针是合理的)。
    * 需要使用到输入参数的指针或引用形式。

    为什么要使用const T&形式?

    以值传入是最为安全的形式,因为它总是提供一个复本到函数中。对于复杂的参数(结构或类),这也引入了不必要的拷贝的开销。使用指针及引用都可以解决这个问题。而引用则更为安全,可以避免一些不必要的空指针判断。所以输入参数以const T&的形式的定义, 与传递值的语义相似,既避免了拷贝,又避免了意外修改。

    下面这个例子,则表现出函数即使定义为const T&形式,仍然可能出现空指针引入的问题:

     void test(const A& a) { 
        a.max = 10;
     }
    
     A* b = NULL;
     test(*b);

    这是一个错误使用引用的示范,语法上合法,但这样的实现是不允许的。判空的责任在于调用者,而不在函数。(参考:How do you check for NULL when passing by reference in C++?

    另外,因为传引用,在其本质也是以指针形式提供的,所以在性能相对于传值会低一些的。所以简单的数据类型还是要传值。

    输出参数为什么是指针呢

    以引用和指针的形式,都可以作为函数的输出参数。如果没有const修饰引用,则引用形式的参数就可以成为一个输出参数。这可能会让代码的读者对参数的类型产生错觉。正是Google C++ Coding Style中所描的: 引用有着和值类的语法,但却是指针的语义。代码的读者会对能不能改变一个参数的值产生疑问, 以为传入的是Value, 但值却改变了。虽然看一下函数声明就可以了,但如果一个大型项目,还是要追求做到一目了然。

    总结

    作为编码规范定义出来的,主要是为了统一大家的编码习惯,减少一些”惊喜”。单纯从传值,传引用,亦或传指针的形式,cplusplus.com上的一篇也可以作为参考When to pass parameters by value, reference, and pointer。总结一下参数三种传入形式的核心点:
    1. 传值性能最高,但有拷贝的开销。
    2. 传引用时空值是不合法的,不用判空,没有拷贝的开销。
    3. 传指针时空值是合法的,需要判空,也没有拷贝的开销。

    展开全文
  • 从Java到C++——指针与引用

    千次阅读 2014-07-30 22:50:48
    从Java到C++——指针与引用C++即有指针又有引用,而且很多时候具有相似的功能,常常容易让人混淆...如下图所示: C++中的引用与指针引用引用是为变量或对象起的另外一个别名,定义形式:T& v; T为类型,v为变量名。

    从Java到C++——指针与引用

    C++即有指针又有引用,而且很多时候具有相似的功能,常常容易让人混淆,着实让人头痛。用两句通俗的话说明两者本质的含意:引用就是一个变量或对象的别名(引用的本质是一个对象);指针是一个段内存空间的地址(指向存储一个变量值的空间或一个对象的空间);如下图所示:



     

    C++中的引用与指针

    引用

    引用是为变量或对象起的另外一个别名,定义形式:T& v;  T为类型,v为变量名。使用引用时,注意以下几点:

    1.引用在创建的时候必须被初始化(指针可以在任何时候赋值)

    2.一旦引用初始化后,就不能改变引用所指向的变量(或对象),一直和该变量(或对象)邦定在一起

    3.引用必须与一个确定的合法内存单元相关联。不存在NULL引用。(指针可以为NULL)

    下面用例子来解释,【例1】:

    void Reference()

    {

    //int &r1; //不符第1要点, 报错  Error:refercece value "r" requires an intializer

    //int & r2 = 100; //非const类型的引用,不能与常量邦定在一起

    int i = 10;

    int &r3 = i; //引用r2与变量i邦定在一起,符合第1要点

    cout << "初始值  i:" << i << "   r3:"  << r3 << endl;

    i = 15; //改变i的值,r3跟着改变,因为i和r3是指向同一块内存,符合第2要点

    cout << "改变i   i:" << i << "   r3:"  << r3 << endl;

    r3 = 20; //改变r3的值,i跟着改变,因为i和r3是指向同一块内存是,符合第2要点

    cout << "改变r3  i:" << i << "   r3:"  << r3 << endl;

    int i2 = 25;

    r3 = i2; //并不是引用r3指向了变量i2,而是i2的值赋给了变量i(r3所指向的变量),符合第2要点

    cout << "赋值r3  i:" << i << "   r3:"  << r3 << "   i2:" << i2 << endl;

    int& r4 = r3; //用引用r3指向的变量i的值初始化引用r4,所用r3,r4邦定的是同一个变量i;r3、r4、i指向同一块内存

    cout << "引用r4  i:" << i << "   r3:"  << r3 << "   r4:" << r4 << endl;

    Data d;

    Data& rData = d; //也可对对象进行引用,原理与变量一样。

    cout << "d.iVal:" << d.iVal << "   rData.iVal:" << rData.iVal << endl;

    d.iVal = 8;

    cout << "d.iVal:" << d.iVal << "   rData.iVal:" << rData.iVal << endl;

    }

    结果:

    初始值  i:10   r3:10

    改变i   i:15   r3:15

    改变r3  i:20   r3:20

    赋值r3  i:25   r3:25   i2:25

    引用r4  i:25   r3:25   r4:25

    d.iVal:0   rData.iVal:0

    d.iVal:8   rData.iVal:8

     

    我们也可以用debug模式对它进行调试,这样可以看到各个变量的内存地址,如下:



     

     

    指针

    指针是指向另外一个类型的复合类型,定义形式:T* p; T为类型,p为指针变量。与引用类似,指针也实现了其它变量或对象的间接访问。使用指针变量p时,在p的前面加上*(即:*p)就是解引用符,用来访问指针所指向的对象。指针具有以下特点:

    1.指针本身就是一个对象,允许对指针进行赋值和拷贝;

    2.指针的生命周期内它可以先后指向几个不同的对象;

    3.指针无须在定义时赋初值;

    4.与内置类型一样,如果指针没有初始化,将指向一个不确定的值;

    5.不能定义指向引用的指针(因为引用不是对象,没有实际的地址)。

    【例2】

    void TestPointer()

    {

    double* p1; //定义一个指向double类型的指针p1,指针未被初始化,可能指向任意一个地址

    double dVal1 = 2; 

    p1 = &dVal1; //给指针p1赋值, &是取地址符,也就是把dVal1的地址赋给p1

    cout << "p1:" << p1 << "   *p1:" << *p1 << endl; //*是解引用符,*p1也就是获取指针p1所指向的变量dVal1的值

    double* p2 = p1; //定义指针p2,同时将p1的值赋给p2,这时p1和p2指向同一个地址

    cout << "p1:" << p1 << "   p2:" << p2 << "   *p1:" << *p1 << "   *p2:" << *p2 << endl;

    }

    结果:

    p1:001AF6B8

    *p1:2

    p1:001AF6A8   p2:001AF6A8   *p1:5   *p2:5

     

    我们也可以用debug模式对它进行调试,这样可以看到各个变量的内存地址,如下:



     

    指针的值的状态

    指针的值(即地址)应是下面四种状态之一:

    1.指向一个对象(或内置类型变量);

    2.指向紧邻对象所占空间的下一个位置;

    3.空指针,意味着没有指向任何对象;

    4.无效指针,也就是以上情况之外的其它值。

    举例解释【例3】

    void TestPointer2()

    {

    short sInt = 65;

    short *sP; //状态4,未被初始化,无效指针

    //cout << sP << endl; //错误,将报异常:The variable 'sP' is being used without being initialized.

    sP = &sInt; //状态1,指向变量ch

    cout << "cP:" << sP << "  *cP:" << *sP << endl;

    sP ++; //状态2,指向变量sInt所在地址的下一个地址

    cout << "cP:" << sP << endl;

    sP = NULL; //状态3,空指针

    cout << "cP:" << sP << endl;

    }

    结果:

    cP:0037FD54  *cP:65

    cP:0037FD56

    cP:00000000

     

     

    易错点

    对于初学者或是从其它语言转向c++的人来说,指针和引用这部分比较难,我觉得主要有以下几点,也是大家需要注意的:

     

    1.&符号的多意性(多个用途)

    &即用在引用也用在指针。定义引用变量,一般在“=”的左侧,在类型后加&符号(如果是在一行内定义多个引用,则每个变量名前加&);表示取变量地址,一般在“=”的右侧用于给指针赋值,&在变量名前面。

    void TestSymbol()

    {

    int nVal1 = 5;

    int nVal2 = 6;

    int nVal3 = 9;

    int& rVal1 = nVal1; //定义引用

    int &rVal2 = nVal2, &rVal3 = nVal3; //定义引用

    cout << "rVal1:" << rVal1 << "  rVal2:" << rVal2 << "  rVal3:" << rVal3 << endl;

     

    int *p1, *p2, *p3;

    p1 = &nVal1; //取nVal1的地址,给p1赋值

    p2 = &nVal2, p3 = &nVal3; //取nVal2, nVal3地址,分别给p2、p3赋值

    cout << "*p1:" << *p1 << "  *p2:" << *p2 << "  *p3:" << *p3 << endl;

    }

     

    2.引用和指针的定义

    一行内定义多个引用,每个引用前都要加&;一行内定义多个指针,每个引用前都要加*。引用的类型要和它所邦定的变量或对象匹配;指针的类型要和它所指向的变量或对象匹配。

    void ReferencePointer()

    {

    int nVal1 = 10;

    int nVal2 = 20;

    int &rVal1 = nVal1, &rVal2 = nVal2;

    cout << "rVal1:" << rVal1 << "  rVal2:" << rVal2 << endl;

    int *p1 = &nVal1, *p2 = &nVal2, *p3 = &nVal2; //p2和p3指向同一个地址

    cout << "*p1:" << *p1 << "    *p2:" << *p2 << endl;

    double dVal = 10.125;

    //double& rDVal = nVal1; //类型不匹配,编译错误

    //double *p = &nVal1; //类型不匹配,编译错误

    }

    结果:

    rVal1:10  rVal2:20

    *p1:10    *p2:20


    展开全文
  • C++ 引用的本质

    千次阅读 多人点赞 2015-07-08 16:33:22
    引用是C++引入的重要机制,它使原来在C中必须用指针实现的功能有了另一种实现的选择,在书写形式上更为简洁。那么引用的本质是什么,它与指针又有什么关系呢?
  • C++引用与const引用

    千次阅读 2007-07-04 17:34:00
    C++引用与const引用(1)在实际的程序中,引用主要被用做函数的形式参数--通常将类对象传递给一个函数.引用必须初始化. 但是用对象的地址初始化引用是错误的,我们可以定义一个指针引用.int ival = 1092;int &re = ...
  • C++ const引用详解

    千次阅读 2013-12-25 16:39:36
    (1) 在实际的程序中,引用主要被用做函数的形式参数--通常将类对象传递给一个函数.引用必须初始化. 但是用对象的地址初始化引用是错误的,我们可以定义一个指针引用。 1 int ival = 1092; 2 int &re = ival;...
  • 【C++注意事项】3 引用

    千次阅读 2015-05-20 22:11:10
    通俗来讲,引用(reference)就是给对象另外一个名字。1)引用必须被初始化int &ref; // 错误int val=10; int &ref2=val; // ref2指向val(val的另一个名字)在初始化变量时,初始值会被拷贝到新建的对象中。在定义...
  • c++ const引用和非const引用

    千次阅读 2013-04-18 00:47:37
    const引用可读可改,与绑定对象是否为const无关,注意区分const引用与对const对象的引用 非const引用可读可改,只可与非const对象绑定 const int ival = 1024; const int &refVal = ival; // ok: ...
  • 但是Java的机制与C++不同,Java中的引用也叫句柄,或者说句柄才是其真实名称。类声明的都是一个句柄,调用构造函数才会使得句柄指向类实例。因此Java中没有类似于C++中的复制函数,因为Java的复制都是直接复制句柄...
  • Cpp_引用

    千次阅读 2016-02-25 22:32:46
    */引用必须做初始化,而且一经初始化其所引用的目标就能更换。引用对临时变量(匿名对象的作用)任何出现字面值常量、计算表达式、类型转换、函数返回值的场合,都会有临时变量(匿名变量)产生。只能用带有常属性...
  • C++引用 && 指针

    千次阅读 2011-11-25 09:46:51
    4.指针和引用有什么分别;如果传引用比传指针安全,为什么?... (2) 存在NULL引用引用必须与合法的存储单元关联;而指针则可以是NULL.   (3) 引用一旦被初始化为指向一个对象,它就
  • 而关于值传递,指针传递,引用传递这几个方面还会存在误区, 所有我觉的有必要在这里也说明一下~下文会通过例子详细说明哦值传递:形参是实参的拷贝,改变形参的值并会影响外部实参的值。从被调用函数的角度来说,...
  • c 结构体的嵌套引用解读

    万次阅读 2013-06-23 11:11:28
    c 结构体的嵌套引用解读 背景:在Linux内核系统中经常能看到如下例1形式的结构体嵌套引用,在代码追踪... 在一个结构内部包含一个类型为该结构体自身的成员是不合法的。 如下:  struct SELF_REF1 { int a; str
  • C++引用和指针的区别

    千次阅读 2020-07-10 14:51:40
    作者:RainMan ...来源:知乎 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 引用是C++引入的重要机制...引用被称为变量的别名,它能脱离被引用对象独立存在,这是在高级语言层面的概念和理.
  • C++:const和引用

    千次阅读 2016-01-28 18:24:50
    定义方式: 将声明符写成&d的形式来定义引用类型其中d是声明的变量名, int size = 100; int &sum = size; 要注意的是我们在引用的时候必须要给引用赋值,例如: int &size; 这种方式是可以的,在一般的...
  • Excel-查找与引用函数

    万次阅读 2018-08-29 13:03:58
    1.ADDRESS(row_num, column_num, [abs_num],... 一个数值,指定要在单元格引用中使用的行号。 column_num 必需。 一个数值,指定要在单元格引用中使用的列号。 abs_num 可选。 一个数值,指定要返回的引用类型。...
  • C++中指针和引用的区别(超详细)

    万次阅读 多人点赞 2015-11-10 17:40:31
    引用初始化后能被改变,指针可以改变所指的对象。 存在指向空值的引用,但是存在指向空值的指针。 注意:引用作为函数参数时,会引发一定的问题,因为让引用作参数,目的就是想改变这个引用所指向地址的内容...
  • c++学习(2.3)引用

    千次阅读 2016-04-28 12:20:27
    在c++11版本中引入了“右值引用”, 关于这个我们在这里先讲解。 这种引用主要作用于内置类型。 严格的来说, 我们使用术语“引用”的时候, 默认的就是左值引用引用就像是为对象起了另外一个名字, 引用类型...
  • 引用的用法

    千次阅读 2008-11-18 19:15:00
    最近看书,看到了引用,对其用法不是很了解。从各处汇总了一些知识,如下: 什么是引用引用是某一变量(目标)的一个别名,对引用的操作与对变量直接操作完全一样。引用的声明方法:类型标识符 &引用名=目标变量名...
  • 网络上有很多讨论C++ 的“引用”与“指针“的区别的文章,谈到区别,其中有一条:“引用不能为空(NULL),引用必须与合法的存储单元关联,指针则可以是NULL)”,但在实际应用中,有时候为了保持一致性,我们会抛开...
  • 对指针和引用的理解? 指针和引用的区别?
  • C/C++何时使用引用和指针

    千次阅读 2016-08-13 11:25:53
    指针与引用看上去完全不同,但是它们似乎有相同的功能。指针与引用都是让你间接引用其他对象。你如何决定在什么时候使用指针,在什么时候使用引用呢?
  • 现代C++之万能引用、完美转发、引用折叠0.导语1.问题引入2.引入万能引用3.万能引用出现场合4.理解左值与右值4.1 精简版4.2 完整版4.3 生命周期延长4.4 生命周期延长应用...
  • (转F001) Rust : 解引用,自动解引用

    千次阅读 2018-11-25 21:10:19
    “解引用(Deref)”是“引用(Ref)”的反操作。比如说,我们有引用类型let p: &amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;T;,那么可以用*符号执行解引用操作,let v: T = p;。如果p的类型是&amp;...
  • 引用其他Bean 实例 ref元素的3个属性 引用父容器中的Bean实例 内部Bean null值 级联属性概述在Spring配置文件中,不但可以将String、int等字面值注入bean中,还可以将集合、map等类型的数据注入Bean中, 此外还可以...
  • 传值、传引用、传值

    万次阅读 2013-07-12 15:20:54
    一、 函数参数传递机制的基本理论  函数参数传递机制问题在本质上是调用... 值传递(passl-by-value)过程中,被调函数的形式参数作为被调函数的局部变量处理,即在堆栈中开辟了内存空间以存放由主调函数放进来
  • 引用与指针的区别

    千次阅读 2013-11-09 11:05:17
    在c++函数中,形式参数用引用和用指针都可以起到在被调用函数中改变调用函数的变量的作用。什么时候用引用作参数?什么时候用指针作参数呢 void function (int *ptr); // 指针 void function(int &ref); // 引用 ...
  • 这个上次面试就问我指针和引用的区别,我就有点蒙圈了,因为对“引用”这个词确实了解,然后面试官又问我知知道值传递和地址传递,我差点拍案而起,心里想问我这个问题,是不是有点太简单了,然后回答的是:“值...
  • C++中引用(reference)的用法详解

    万次阅读 2013-12-26 18:22:52
    C++中引用(reference)的用法详解 TOC 1.简介 2.引用的语法 3.引用使用技巧  3.1 引用和多态  3.2 作为参数  3.3 作为返回值  3.4 什么时候使用引用 4. 参考资料 1.简介  引用是C++引入的新语言特性。从...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 88,590
精华内容 35,436
关键字:

引用形式不合法