How to return a class object by reference in C++?

时间:2022-02-04 16:55:24

I have a class called Object which stores some data.

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

I would like to return it by reference using a function like this:

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

    Object& return_Object();

Then, in my code, I would call it like this:

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

    Object myObject = return_Object();

I have written code like this and it compiles. However, when I run the code, I consistently get a seg fault. What is the proper way to return a class object by reference?

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

5 个解决方案

#1


37  

You're probably returning an object that's on the stack. That is, return_Object() probably looks like this:

您可能正在返回堆栈中的对象。也就是说,return_Object()可能如下所示:

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

    return object_to_return;
}

If this is what you're doing, you're out of luck - object_to_return has gone out of scope and been destructed at the end of return_Object, so myObject refers to a non-existent object. You either need to return by value, or return an Object declared in a wider scope or newed onto the heap.

如果这是你正在做的事情,那你就不幸了 - object_to_return已超出范围并在return_Object结束时被破坏,因此myObject引用了一个不存在的对象。您需要按值返回,或者返回在更宽范围内声明的或在堆上新建的Object。

#2


19  

You can only use

你只能使用

     Object& return_Object();

if the object returned has a greater scope than the function. For example, you can use it if you have a class where it is encapsulated. If you create an object in your function, use pointers. If you want to modify an existing object, pass it as an argument.

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

  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;
         }
   };

#3


13  

You can only return non-local objects by reference. The destructor may have invalidated some internal pointer, or whatever.

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

Don't be afraid of returning values -- it's fast!

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

#4


1  

Well, it is maybe not a really beautiful solution in the code, but it is really beautiful in the interface of your function. And it is also very efficient. It is ideal if the second is more important for you (for example, you are developing a library).

好吧,它可能不是代码中非常漂亮的解决方案,但它在您的功能界面中非常漂亮。它也非常有效。如果第二个对您来说更重要(例如,您正在开发库),这是理想的。

The trick is this:

诀窍是:

  1. A line A a = b.make(); is internally converted to a constructor of A, i.e. as if you had written A a(b.make());.
  2. A A a = b.make();在内部转换为A的构造函数,即好像你已经写了A a(b.make());.
  3. Now b.make() should result a new class, with a callback function.
  4. 现在b.make()应该产生一个带有回调函数的新类。
  5. This whole thing can be fine handled only by classes, without any template.
  6. 这整个事情只能通过类来处理,没有任何模板。

Here is my minimal example. Check only the main(), as you can see it is simple. The internals aren't.

这是我的最小例子。只检查main(),因为你可以看到它很简单。内部不是。

From the viewpoint of the speed: the size of a Factory::Mediator class is only 2 pointers, which is more that 1 but not more. And this is the only object in the whole thing which is transferred by value.

从速度的角度来看:Factory :: Mediator类的大小只有2个指针,超过1但不多。而这是整个事物中唯一被价值转移的对象。

#include <stdio.h>

class Factory {
  public:
    class Mediator;

    class Result {
      public:
        Result() {
          printf ("Factory::Result::Result()\n");
        };

        Result(Mediator fm) {
          printf ("Factory::Result::Result(Mediator)\n");
          fm.call(this);
        };
    };

    typedef void (*MakeMethod)(Factory* factory, Result* result);

    class Mediator {
      private:
        Factory* factory;
        MakeMethod makeMethod;

      public:
        Mediator(Factory* factory, MakeMethod makeMethod) {
          printf ("Factory::Mediator::Mediator(Factory*, MakeMethod)\n");
          this->factory = factory;
          this->makeMethod = makeMethod;
        };

        void call(Result* result) {
          printf ("Factory::Mediator::call(Result*)\n");
          (*makeMethod)(factory, result);
        };
    };
};

class A;

class B : private Factory {
  private:
    int v;

  public:
    B(int v) {
      printf ("B::B()\n");
      this->v = v;
    };

    int getV() const {
      printf ("B::getV()\n");
      return v;
    };

    static void makeCb(Factory* f, Factory::Result* a);

    Factory::Mediator make() {
      printf ("Factory::Mediator B::make()\n");
      return Factory::Mediator(static_cast<Factory*>(this), &B::makeCb);
    };
};

class A : private Factory::Result {
  friend class B;

  private:
    int v;

  public:
    A() {
      printf ("A::A()\n");
      v = 0;
    };

    A(Factory::Mediator fm) : Factory::Result(fm) {
      printf ("A::A(Factory::Mediator)\n");
    };

    int getV() const {
      printf ("A::getV()\n");
      return v;
    };

    void setV(int v) {
      printf ("A::setV(%i)\n", v);
      this->v = v;
    };
};

void B::makeCb(Factory* f, Factory::Result* r) {
      printf ("B::makeCb(Factory*, Factory::Result*)\n");
      B* b = static_cast<B*>(f);
      A* a = static_cast<A*>(r);
      a->setV(b->getV()+1);
    };

int main(int argc, char **argv) {
  B b(42);
  A a = b.make();
  printf ("a.v = %i\n", a.getV());
  return 0;
}

#5


0  

I will show you some examples:

我将向您展示一些例子:

First example, do not return local scope object, for example:

const string &mainip(const string &s)
{
    string ret=s;

    //  operator ret

    return ret;
}

you can't return ret by reference, because ret is destructed at the end.

你不能通过引用返回ret,因为ret在最后被破坏了。

Second example, you can return by reference:

const string &shorterString(const string &s1,const string &s2)
{
    return s1.size()<s2.size()?s1:s2;
}

you can return by reference for both s1 and s2 is still existing.

您可以通过引用返回s1和s2仍然存在。

Third example:

char &get_val(string &str,string::size_type ix)
{
    return str[ix];
}

usage code as below:

使用代码如下:

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

because after return by reference the object is still exists;

因为通过引用返回后对象仍然存在;

Fourth example

class Student{
    public:
        string m_name;
        int age;    

        string& getName();
};

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

// you can return by reference, after this function stu object is still exists
string& Test(Student &stu)
{
    return stu.m_name;
}

usage example:

用法示例:

Student stu;
stu.m_name = 'jack';
string name = stu.getName(); // 
//or 
string name2 = Test(stu);

Fifth example:

class String{
    private:
        char* str_;

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

// for example a=b=c usage
String& String::operator =(const String &str)   
{
    if (this == &str)
    {
        return *this;
    }
    delete [] str_;
    int len = strlen(str.str_);
    str_ = new char[len+1];
    strcpy(str_,str.str_);
    return *this;
}

#1


37  

You're probably returning an object that's on the stack. That is, return_Object() probably looks like this:

您可能正在返回堆栈中的对象。也就是说,return_Object()可能如下所示:

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

    return object_to_return;
}

If this is what you're doing, you're out of luck - object_to_return has gone out of scope and been destructed at the end of return_Object, so myObject refers to a non-existent object. You either need to return by value, or return an Object declared in a wider scope or newed onto the heap.

如果这是你正在做的事情,那你就不幸了 - object_to_return已超出范围并在return_Object结束时被破坏,因此myObject引用了一个不存在的对象。您需要按值返回,或者返回在更宽范围内声明的或在堆上新建的Object。

#2


19  

You can only use

你只能使用

     Object& return_Object();

if the object returned has a greater scope than the function. For example, you can use it if you have a class where it is encapsulated. If you create an object in your function, use pointers. If you want to modify an existing object, pass it as an argument.

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

  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;
         }
   };

#3


13  

You can only return non-local objects by reference. The destructor may have invalidated some internal pointer, or whatever.

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

Don't be afraid of returning values -- it's fast!

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

#4


1  

Well, it is maybe not a really beautiful solution in the code, but it is really beautiful in the interface of your function. And it is also very efficient. It is ideal if the second is more important for you (for example, you are developing a library).

好吧,它可能不是代码中非常漂亮的解决方案,但它在您的功能界面中非常漂亮。它也非常有效。如果第二个对您来说更重要(例如,您正在开发库),这是理想的。

The trick is this:

诀窍是:

  1. A line A a = b.make(); is internally converted to a constructor of A, i.e. as if you had written A a(b.make());.
  2. A A a = b.make();在内部转换为A的构造函数,即好像你已经写了A a(b.make());.
  3. Now b.make() should result a new class, with a callback function.
  4. 现在b.make()应该产生一个带有回调函数的新类。
  5. This whole thing can be fine handled only by classes, without any template.
  6. 这整个事情只能通过类来处理,没有任何模板。

Here is my minimal example. Check only the main(), as you can see it is simple. The internals aren't.

这是我的最小例子。只检查main(),因为你可以看到它很简单。内部不是。

From the viewpoint of the speed: the size of a Factory::Mediator class is only 2 pointers, which is more that 1 but not more. And this is the only object in the whole thing which is transferred by value.

从速度的角度来看:Factory :: Mediator类的大小只有2个指针,超过1但不多。而这是整个事物中唯一被价值转移的对象。

#include <stdio.h>

class Factory {
  public:
    class Mediator;

    class Result {
      public:
        Result() {
          printf ("Factory::Result::Result()\n");
        };

        Result(Mediator fm) {
          printf ("Factory::Result::Result(Mediator)\n");
          fm.call(this);
        };
    };

    typedef void (*MakeMethod)(Factory* factory, Result* result);

    class Mediator {
      private:
        Factory* factory;
        MakeMethod makeMethod;

      public:
        Mediator(Factory* factory, MakeMethod makeMethod) {
          printf ("Factory::Mediator::Mediator(Factory*, MakeMethod)\n");
          this->factory = factory;
          this->makeMethod = makeMethod;
        };

        void call(Result* result) {
          printf ("Factory::Mediator::call(Result*)\n");
          (*makeMethod)(factory, result);
        };
    };
};

class A;

class B : private Factory {
  private:
    int v;

  public:
    B(int v) {
      printf ("B::B()\n");
      this->v = v;
    };

    int getV() const {
      printf ("B::getV()\n");
      return v;
    };

    static void makeCb(Factory* f, Factory::Result* a);

    Factory::Mediator make() {
      printf ("Factory::Mediator B::make()\n");
      return Factory::Mediator(static_cast<Factory*>(this), &B::makeCb);
    };
};

class A : private Factory::Result {
  friend class B;

  private:
    int v;

  public:
    A() {
      printf ("A::A()\n");
      v = 0;
    };

    A(Factory::Mediator fm) : Factory::Result(fm) {
      printf ("A::A(Factory::Mediator)\n");
    };

    int getV() const {
      printf ("A::getV()\n");
      return v;
    };

    void setV(int v) {
      printf ("A::setV(%i)\n", v);
      this->v = v;
    };
};

void B::makeCb(Factory* f, Factory::Result* r) {
      printf ("B::makeCb(Factory*, Factory::Result*)\n");
      B* b = static_cast<B*>(f);
      A* a = static_cast<A*>(r);
      a->setV(b->getV()+1);
    };

int main(int argc, char **argv) {
  B b(42);
  A a = b.make();
  printf ("a.v = %i\n", a.getV());
  return 0;
}

#5


0  

I will show you some examples:

我将向您展示一些例子:

First example, do not return local scope object, for example:

const string &mainip(const string &s)
{
    string ret=s;

    //  operator ret

    return ret;
}

you can't return ret by reference, because ret is destructed at the end.

你不能通过引用返回ret,因为ret在最后被破坏了。

Second example, you can return by reference:

const string &shorterString(const string &s1,const string &s2)
{
    return s1.size()<s2.size()?s1:s2;
}

you can return by reference for both s1 and s2 is still existing.

您可以通过引用返回s1和s2仍然存在。

Third example:

char &get_val(string &str,string::size_type ix)
{
    return str[ix];
}

usage code as below:

使用代码如下:

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

because after return by reference the object is still exists;

因为通过引用返回后对象仍然存在;

Fourth example

class Student{
    public:
        string m_name;
        int age;    

        string& getName();
};

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

// you can return by reference, after this function stu object is still exists
string& Test(Student &stu)
{
    return stu.m_name;
}

usage example:

用法示例:

Student stu;
stu.m_name = 'jack';
string name = stu.getName(); // 
//or 
string name2 = Test(stu);

Fifth example:

class String{
    private:
        char* str_;

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

// for example a=b=c usage
String& String::operator =(const String &str)   
{
    if (this == &str)
    {
        return *this;
    }
    delete [] str_;
    int len = strlen(str.str_);
    str_ = new char[len+1];
    strcpy(str_,str.str_);
    return *this;
}