如何在C++中通过引用返回一个类对象?

use*_*171 35 c++ reference segmentation-fault return-by-reference

我有一个名为Object的类,它存储一些数据.

我想通过引用使用如下函数返回它:

    Object& return_Object();
Run Code Online (Sandbox Code Playgroud)

然后,在我的代码中,我会这样称呼它:

    Object myObject = return_Object();
Run Code Online (Sandbox Code Playgroud)

我编写了这样的代码并编译.但是,当我运行代码时,我总是遇到一个seg错误.通过引用返回类对象的正确方法是什么?

Cho*_*ett 49

您可能正在返回堆栈中的对象.也就是说,return_Object()可能看起来像这样:

Object& return_Object()
{
    Object object_to_return;
    // ... do stuff ...

    return object_to_return;
}
Run Code Online (Sandbox Code Playgroud)

如果这就是你正在做的事情,那你运气不好 - object_to_return已经超出了范围并且在结束时被破坏了return_Object,所以myObject指的是一个不存在的对象.您需要按值返回,或者Object在更宽的范围内返回声明或者new在堆上返回.


UmN*_*obe 21

你只能使用

     Object& return_Object();
Run Code Online (Sandbox Code Playgroud)

如果返回的对象具有比函数更大的范围.例如,如果您有一个封装它的类,则可以使用它.如果在函数中创建对象,请使用指针.如果要修改现有对象,请将其作为参数传递.

  class  MyClass{
      private:
        Object myObj;

      public:
         Object& return_Object() {
            return myObj;
         }

         Object* return_created_Object() {
            return new Object();
         }

         bool modify_Object( Object& obj) {
            //  obj = myObj; return true; both possible
            return obj.modifySomething() == true;
         }
   };
Run Code Online (Sandbox Code Playgroud)


spr*_*aff 15

您只能通过引用返回非本地对象.析构函数可能使某些内部指针无效.

不要害怕回归价值 - 这很快!


Jay*_*llo 6

我将向您展示一些示例:

第一个例子,不返回局部作用域对象,例如:

const string &dontDoThis(const string &s)
{
    string local = s;
    return local;
}
Run Code Online (Sandbox Code Playgroud)

您不能通过local引用返回,因为localdontDoThis.

第二个例子,你可以通过引用返回:

const string &shorterString(const string &s1, const string &s2)
{
    return (s1.size() < s2.size()) ? s1 : s2;
}
Run Code Online (Sandbox Code Playgroud)

在这里,您可以通过引用返回s1s2因为它们是在shorterString调用之前定义的。

第三个例子:

char &get_val(string &str, string::size_type ix)
{
    return str[ix];
}
Run Code Online (Sandbox Code Playgroud)

使用代码如下:

string s("123456");
cout << s << endl;
char &ch = get_val(s, 0); 
ch = 'A';
cout << s << endl; // A23456
Run Code Online (Sandbox Code Playgroud)

get_val可以s通过引用返回元素,因为s调用后仍然存在。

第四个例子

class Student
{
public:
    string m_name;
    int age;    

    string &getName();
};

string &Student::getName()
{
    // you can return by reference
    return m_name;
}

string& Test(Student &student)
{
    // we can return `m_name` by reference here because `student` still exists after the call
    return stu.m_name;
}
Run Code Online (Sandbox Code Playgroud)

用法示例:

Student student;
student.m_name = 'jack';
string name = student.getName();
// or
string name2 = Test(student);
Run Code Online (Sandbox Code Playgroud)

第五个例子:

class String
{
private:
    char *str_;

public:
    String &operator=(const String &str);
};

String &String::operator=(const String &str)
{
    if (this == &str)
    {
        return *this;
    }
    delete [] str_;
    int length = strlen(str.str_);
    str_ = new char[length + 1];
    strcpy(str_, str.str_);
    return *this;
}
Run Code Online (Sandbox Code Playgroud)

然后你可以operator=像这样使用上面的:

String a;
String b;
String c = b = a;
Run Code Online (Sandbox Code Playgroud)