代码之家  ›  专栏  ›  技术社区  ›  poundifdef

C++声明中的“和”是什么?

  •  32
  • poundifdef  · 技术社区  · 15 年前

    我是一个C家伙,我正在尝试了解一些C++代码。我有以下功能声明:

    int foo(const string &myname) {
      cout << "called foo for: " << myname << endl;
      return 0;
    }
    

    函数签名与等价C有何区别:

    int foo(const char *myname)
    

    使用之间有区别吗 string *myname VS string &myname ?两者有什么区别 & 在C++中 * 用C表示指针?

    类似地:

    const string &GetMethodName() { ... }
    

    什么是 & 在这里做什么?有什么网站可以解释 & 在C与C++中使用不同?

    7 回复  |  直到 6 年前
        1
  •  31
  •   czuger    15 年前

    “&”表示引用,而不是指向对象的指针(在您的情况下是常量引用)。

    具有某种功能的优势,如

    foo(string const& myname) 
    

    结束

    foo(string const* myname)
    

    在前一种情况下,您保证MyNess是非空的,因为C++不允许空引用。因为您是通过引用传递的,所以不会复制对象,就像传递指针一样。

    第二个例子:

    const string &GetMethodName() { ... }
    

    将允许您返回对成员变量(例如)的常量引用。如果不希望返回副本,并且再次确保返回的值不为空,则此选项非常有用。例如,下面允许您直接、只读访问:

    class A
    {
      public:
      int bar() const {return someValue;}
      //Big, expensive to copy class
    }
    
    class B
    {
    public:
     A const& getA() { return mA;}
    private:
     A mA;
    }
    void someFunction()
    {
     B b = B();
     //Access A, ability to call const functions on A
     //No need to check for null, since reference is guaranteed to be valid.
     int value = b.getA().bar(); 
    }
    

    当然,您必须小心不要返回无效的引用。 编译器很乐意编译以下内容(取决于警告级别和如何处理警告)

    int const& foo() 
    {
     int a;
    
     //This is very bad, returning reference to something on the stack. This will
     //crash at runtime.
     return a; 
    }
    

    基本上,您有责任确保返回引用的内容实际上是有效的。

        2
  •  17
  •   xji    6 年前

    在这里, & 不用作运算符。作为函数或变量声明的一部分, & 表示引用。C++ FAQ Lite有一个漂亮的俏皮话。 chapter on references .

        3
  •  6
  •   sohum    15 年前

    string*和string&有两种不同。首先,指针指向数据的地址位置。参考点指向数据。如果您具有以下功能:

    int foo(string *param1);
    

    您必须签入函数声明,以确保param1指向有效的位置。比较:

    int foo(string &param1);
    

    在这里,调用者有责任确保指向的数据是有效的。不能传递“null”值,例如,在上面的第二个函数中。

    关于第二个问题,关于方法返回值作为引用,请考虑以下三个函数:

    string &foo();
    string *foo();
    string foo();
    

    在第一种情况下,您将返回对数据的引用。如果函数声明如下所示:

    string &foo()
    {
        string localString = "Hello!";
        return localString;
    }
    

    您可能会遇到一些编译器错误,因为您返回的是对该函数在堆栈中初始化的字符串的引用。在函数返回时,该数据位置不再有效。通常,您希望返回对类成员的引用或类似的内容。

    上面的第二个函数返回实际内存中的指针,因此它将保持不变。不过,您必须检查空指针。

    最后,在第三种情况下,返回的数据将被复制到调用方的返回值中。所以如果你的功能是这样的:

    string foo()
    {
        string localString = "Hello!";
        return localString;
    }
    

    你会没事的,因为字符串“hello”会被复制到函数的返回值中,可以在调用者的内存空间中访问。

        4
  •  1
  •   FryGuy    15 年前

    查看C++中的(引用)运算符的一种方法是,它仅仅是指向指针的语法糖。例如,以下是 粗略地 当量:

    void foo(int &x)
    {
        x = x + 1;
    }
    
    void foo(int *x)
    {
        *x = *x + 1;
    }
    

    更有用的是在处理类时,使方法从x->bar()转换为x.bar()。

    我说的原因 粗略地 使用引用会对您可以对引用执行的操作施加额外的编译时限制,以防止在处理指针时出现某些问题。例如,您不能意外地更改指针,或以任何方式使用指针,而不是引用已传递的单数对象。

        5
  •  1
  •   Chinmay Kanchi    15 年前
    #include<iostream>
    using namespace std;
    int add(int &number);
    
    int main ()
    {
                int number;
                int result;
                number=5;
                cout << "The value of the variable number before calling the function : " << number << endl;
                result=add(&number);
                cout << "The value of the variable number after the function is returned : " << number << endl;
                cout << "The value of result : " << result << endl;
                return(0);
    }
    
    int add(int &p)
    {
                *p=*p+100;
                return(*p);
    }
    

    这是几项无效代码。通过g++运行它可以得到:

    crap.cpp: In function ‘int main()’:
    crap.cpp:11: error: invalid initialization of non-const reference of type ‘int&’ from a temporary of type ‘int*’
    crap.cpp:3: error: in passing argument 1 of ‘int add(int&)’
    crap.cpp: In function ‘int add(int&)’:
    crap.cpp:19: error: invalid type argument of ‘unary *’
    crap.cpp:19: error: invalid type argument of ‘unary *’
    crap.cpp:20: error: invalid type argument of ‘unary *’
    

    代码的有效版本为:

    #include<iostream>
    using namespace std;
    int add(int &number);
    
    int main ()
    {
                int number;
                int result;
                number=5;
                cout << "The value of the variable number before calling the function : " << number << endl;
                result=add(number);
                cout << "The value of the variable number after the function is returned : " << number << endl;
                cout << "The value of result : " << result << endl;
                return(0);
    }
    
    int add(int &p)
    {
                p=p+100;
                return p;
    }
    

    这里所发生的是,您正在向函数传递一个变量“原样”。这大致相当于:

    int add(int *p)
    {
          *p=*p+100;
          return *p;
    }
    

    但是,将引用传递给函数可以确保不能使用引用执行指针算术之类的操作。例如:

    int add(int &p)
    {
                *p=*p+100;
                return p;
    }
    

    无效。

    如果你 必须 使用指向引用的指针,必须显式执行以下操作:

    int add(int &p)
    {
                        int* i = &p;
                i=i+100L;
                return *i;
    }
    

    它在测试运行时提供(如预期的)垃圾输出:

    The value of the variable number before calling the function : 5
    The value of the variable number after the function is returned : 5
    The value of result : 1399090792
    
        6
  •  1
  •   seaotternerd    9 年前

    您的函数声明了一个常量 参考 字符串:

    int foo(const string &myname) {
      cout << "called foo for: " << myname << endl;
      return 0;
    }
    

    引用具有一些特殊的属性,这使得它在许多方面更安全地替代指针:

    • 不能为空
    • 必须始终初始化
    • 一旦设置,就不能更改为引用其他变量
    • 它的使用方式与它所引用的变量完全相同(这意味着您不需要像指针一样尊重它)。

    函数签名与等价C有何区别:

    int foo(const char *myname)
    

    有几个不同之处,因为第一个直接引用一个对象,而 const char* 必须取消引用以指向数据。

    使用string*myname和string&myname有什么区别吗?

    处理参数时的主要区别在于不需要取消引用 &myname . 一个简单的例子是:

    int add_ptr(int *x, int* y)
    {
        return *x + *y;
    }
    int add_ref(int &x, int &y)
    {
        return x + y;
    }
    

    做同样的事情。在这种情况下,唯一的区别是您不需要取消引用 x y 因为它们直接引用传入的变量。

    const string &GetMethodName() { ... }
    

    这里在做什么?是否有一些网站解释了C和C++如何以及如何使用不同的网站?

    这将返回对字符串的常量引用。所以调用者可以直接访问返回的变量,但只能从只读的意义上访问。这有时用于返回字符串数据成员,而不分配额外的内存。

    有一些微妙的参考-看看 C++ FAQ on References 更多细节。

        7
  •  0
  •   Carson Myers    15 年前

    在这种背景下 & 使函数 stringname 参考文献。 引用和指针之间的区别是:

    • 当您引用一个变量时,该引用 您引用的变量。您不需要取消引用它或任何东西,使用引用在语义上等于使用引用变量本身。
    • NULL 不是引用的有效值,将导致编译器错误。一般来说,如果您想在C++函数中使用输出参数(或一般的指针/引用),则应该允许将空值传递给该参数,然后使用指针(或智能指针,最好是)。如果传递空值对该函数没有意义,请使用引用。
    • 你不能“坐”一个参照物。虽然指针的值可以更改为指向其他对象,但引用没有类似的功能。一旦通过引用获取一个变量,就可以有效地直接处理该变量。就像你不能改变 a 通过写作 b = 4; . 引用的值是它引用的任何对象的值。