【问题标题】:Pointers and references in C++C++ 中的指针和引用
【发布时间】:2015-04-21 02:27:47
【问题描述】:

我对 C++ 相当陌生,因此试图准确地理解指针和引用是如何工作的。因此,我有一个简单的程序,它应该引用一个字符串并返回对另一个字符串的引用。 我也不想抄。 这是代码

#include <iostream>
#include <cstdlib>
#include <string>

std::string& string_reverse(std::string& str){
  std::string rev = "";
  for(int i= str.length() -1; i >=0; i--){
    rev+=str[i];
  }
  return &rev;

}

int main(){
  std::string s="";
  std::cout<<"Please enter a string..."<<std::endl;
  std::cin>>s;
  std::cout<< string_reverse(s)<<std::endl;

}

但是我的代码引发了很多错误。如果有人能详细说明可以做到这一点的不同方法以及每种方法的根本原因以及哪种方法是正确的,那将非常有帮助。

【问题讨论】:

  • "返回对另一个字符串的引用" - 它是函数本地的,在你可以对它做任何事情之前就被破坏了。要么按值返回,要么将传递的字符串反转并返回任何内容或对其的引用。
  • 该函数被声明为返回一个引用,但您尝试返回一个指针,地址运算符&amp; 会产生一个指针。但是在你解决了这个简单的问题之后,还有比这更糟糕的问题,即你返回一个对局部变量的引用,这个变量一旦函数退出就会超出范围,你留下一个悬空引用,使用它会导致undefined behavior.
  • 一般来说,当你问这样的问题时,你应该在你的问题中包含错误。您不仅可以让读者更轻松,还可以让他们有机会教您如何阅读错误,以便您自己解决问题!

标签: c++ pointers pass-by-reference


【解决方案1】:

首先,您不会返回作用域局部变量的引用

std::string& string_reverse(std::string& str){
        // ^

改成

std::string string_reverse(std::string& str){

这里不能返回引用,因为函数返回后rev变量会被销毁(另见Can a local variable's memory be accessed outside its scope?)。

其次,您不要使用&amp;创建引用:

 return &rev;
     // ^

这将采用rev 的地址(即指针)。您只需编写(无论哪种情况)

 return rev;

最后但同样重要的是,您不需要为输入参数传递非const 引用。最好写

std::string string_reverse(const std::string& str){ 
                        // ^^^^^

如果函数没有改变str

【讨论】:

    【解决方案2】:

    您正在混合引用和地址,摆脱两者,它会起作用:

    std::string string_reverse(std::string& str){
        std::string rev = "";
        for(int i= str.length() -1; i >=0; i--){
            rev+=str[i];
        }
        return rev;
    
    }
    

    【讨论】:

    • 好的,我得到它编译的代码,但有没有其他方法可以做到这一点。我试图更好地理解通过引用传递。
    • rev 是在本地范围内的堆栈上创建的,因此您不想将对它的引用传递到 string_reverse (其范围)之外!任何体面的编译器实际上都不会进行任何复制,但会构造底层的 string 对象,它会在其中结束。
    【解决方案3】:

    实际的错误是您返回了对将在范围之外销毁的东西的引用。

    【讨论】:

    • 错误较多,OP的代码返回的不是引用,而是指针。
    【解决方案4】:

    这将修复您的错误

    #include <iostream>
    #include <cstdlib>
    #include <string>
    
    std::string string_reverse(std::string& str){   // made change here
      std::string rev = "";
      for(int i= str.length() -1; i >=0; i--){
        rev+=str[i];
      }
      return rev;        // made change here
    
    }
    
    int main(){
      std::string s="";
      std::cout<<"Please enter a string..."<<std::endl;
      std::cin>>s;
      std::cout<< string_reverse(s)<<std::endl;
    
    }
    

    您的代码的问题,正如其他人所建议的那样,变量rev将在函数返回后被销毁(它超出范围),并且您的代码导致未定义的行为。

    这里有一些您可能想阅读的链接(这些链接可以为您提供比我更多的信息,但您必须耐心阅读所有内容)。

    http://www.cs.fsu.edu/~myers/c++/notes/references.html

    http://www.learncpp.com/cpp-tutorial/73-passing-arguments-by-reference/

    http://www.tutorialspoint.com/cplusplus/cpp_function_call_by_reference.htm

    http://www.cplusplus.com/articles/z6vU7k9E/

    【讨论】:

    • 除了 link1, link2, ... 之外,您的链接难道没有更好的标题吗?这实际上看起来并不是很想遵循这些。
    猜你喜欢
    • 2015-02-13
    • 2020-08-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-23
    相关资源
    最近更新 更多