为什么这个程序员特别通过引用传递函数中的指针?

时间:2015-10-02 17:04:53

标签: c++

我看到了这个特殊代码:

void GetMe(User& user) {
     std::cout << user.getName() << std::endl;
}

main(...) {
     User* user = new User("Joe");
     GetMe(*user);
     getchar();
     return EXIT_SUCCESS;
}

我找不到这方面的例子特别是关于Stack溢出的任何问题只有一些用(&amp; *)而不是(&amp;)而且我不明白它背后的意义是什么,是为了安全以防指针在其他地方被删除? (这是一个多线程的应用程序)

4 个答案:

答案 0 :(得分:1)

将用户定义的类型传递给函数时,可以使用以下方法之一:

  1. 按值传递:

    void GetMe(User user) { ... }
    
  2. 通过指针:

    void GetMe(User* userPtr) { ... }
    void GetMe(User const* userPtr) { ... }
    
  3. 通过引用传递:

    void GetMe(User& user) { ... }
    void GetMe(User const& userPtr) { ... }
    
  4. 根据经验,通过引用传递比传递值或通过指针更好。

    当您通过引用而不是值传递时,将避免复制对象的成本。

    当你通过指针时,你不能假设不会传递nullptr。因此,您已在GetMe中添加检查以说明该情况。当你通过引用传递时,你不必担心。

答案 1 :(得分:0)

我相信你在问为什么代码没有写成:

void GetMe(User* user) {
     std::cout << user->getName() << std::endl;
}

main(...) {
     User* user = new User("Joe");
     GetMe(user);
     getchar();
     return EXIT_SUCCESS;
}

但很多有经验的程序员会反而问为什么不是。

void GetMe(User const& user) {
     std::cout << user.getName() << std::endl;
}

main(...) {
     User* user = new User("Joe");
     GetMe(*user);
     getchar();
     return EXIT_SUCCESS;
}

在这两个例子中,我忽略了更严重的内存泄漏非智能指针问题,只是看看用户如何传递给GetMe。

原始与我认为你问的方式主要是一个风格问题。我没有看到多线程或其他功能差异(正如你所问的那样),也没有看到任何一种风格的强烈论据。

但是我确实看到了在通过指针或引用传递时标记它const的强大论据。如果getName()不是const(导致用户更难以使用),则可能也应该修复。

答案 2 :(得分:0)

在我看来,你的问题分为两部分:

  1. 为什么界面void GetMe(User& user) { }代替void GetMe(User* user) {}?可能有以下几个原因:

    void GetMe(User& user) { }表示具有可塑性的非空 输入输出 user。如果您想要不可延展或仅输入,请使用void GetMe(User const& user) { }。如果你想要可以为空,请使用指针等......

  2. 如何在C ++中传递参数具有非常特定的语义,因此您必须小心如何执行此操作。它们都有不同的含义:通过引用,指针,const引用,const指针等传递......

    1. 为什么User* user = new User("Joe");代替User user("Joe");?可能有原因要您在堆上动态分配内存而不是在堆栈上本地分配内存。例如,如果您希望对象的生命周期长于右括号。另一个原因是,如果User是一个非常大的对象,那么你想要它在堆上(使用现代CPU,这可能不是一个问题)。
    2. 请注意,多线程是一种完全不同的蠕虫病毒。您必须担心内存可见性,同步,互斥,竞争条件等......大多数问题都与上述两点正交。如果你不想浪费大量的时间来调试线程问题,我建议你在走这条路之前先掌握基本的C ++语义。

答案 3 :(得分:-2)

默认情况下,参数按值传递给函数,即没有&amp; ,你有一个函数的副本 - 只是复制它的值,而不是它的参考 - 即你没有在函数中有你的真实参数,如果你必须用参数的地址(参考)做一些操作,一切都会出错。

考虑这个例子:一个无法为其参数(char)分配内存的函数:

void al(char * c) //wrong way: pass by value
{
c =new char[10];
}
main()
{
char * x;
al(x);//don't allocated because pass by value/.
 *x='a';//memory error//
 }

但是这个函数声明可以这样做,因为通过引用传递:

 void al(char * & c)