Как вернуть ссылку в C ++ - PullRequest
0 голосов
/ 08 января 2011

Если, например, я создаю новый объект в функции и хочу вернуть его ссылку, как я могу это сделать?

Допустим, у меня есть IntClass, у которого есть поле 'int num' в частном порядке. Поэтому я хочу создать новый элемент IntClass в функции и вернуть ссылку на этот объект. Я пробовал что-то подобное, но это кажется незаконным (по какой-то причине, когда я делаю такую ​​вещь, Binaries удаляется, когда я компилирую код, хотя я не получаю ошибок от самого компилятора (ECLIPSE):

 IntClass* a = new IntClass(10);
 IntClass &ref = *a;
 return ref;

Есть идеи, как вернуть ссылку?

РЕДАКТИРОВАТЬ: разрешено "предполагать", что C ++ использует сборщик мусора

Поскольку большинству из вас непонятно, ПОЧЕМУ я "хочу" сделать это, вот полный вопрос:

Я получил этот файл (не сделан мной и не может быть отредактирован):

poly_subtype.h

#ifndef POLY_SUBTYPE_H
#define POLY_SUBTYPE_H
#include <iostream>
#include "cpu_add.h"
using std::cout;
using std::endl;

//Deriving classes definition
class IntClass;
class DoubleClass;

//The Virtual Number Class. IntClass and FloatClass will derive from this class.
class Number {
    public:
        //return a Number object that's the results of x+this, when x is DoubleClass
        virtual Number& addDouble(DoubleClass& x) = 0;

        //return a Number object that's the results of x+this, when x is IntClass
        virtual Number& addInt(IntClass& x) = 0;

        //return a Number object that's the results of x+this, when x is either
        //IntClass or DoubleClass
        virtual Number& operator+(Number& x) = 0;

        //Print the number stored in the object
        virtual void print_number() = 0;
};

class IntClass : public Number {
    private:
        int my_number;
    public:
        //Constructor
        IntClass(int n):my_number(n) {}

        //returns the number stored in the object
        int get_number()  {return my_number;}

        //print the number stored in the object
        void print_number() {cout << my_number << endl;}

        //return a DoubleClass object that's the result of x+this
        Number& addDouble(DoubleClass& x);

        //return an IntClass object that's the result of x+this
        Number& addInt(IntClass& x);

        //return a Number object that's the result of x+this.
        //The actual class of the returned object depends on x.
        //If x is IntClass, then the result if IntClass.
        //If x is DoubleClass, then the results is DoubleClass.
        Number& operator+(Number& x);
};

class DoubleClass : public Number {
    private:
        double my_number;
    public:
        //Constructor
        DoubleClass(double n):my_number(n) {}

        //returns the number stored in the object
        double get_number()  {return my_number;}

        //Print the number stored in the object
        void print_number() {cout << my_number << endl;}

        //return a DoubleClass object that's the result of x+this
        Number& addDouble(DoubleClass& x);

        //return a DoubleClass object that's the result of x+this
        Number& addInt(IntClass& x);

        //return a DoubleClass object that's the result of x+this.
        //This should work if x is either IntClass or DoubleClass
        Number& operator+( Number& x);
};

#endif

и у меня есть этот файл (опять же, не написанный мной и не редактируемый - говорит, что я могу использовать эти функции, но не оператор «+».

cpu_add.h:

#ifndef CPU_ADD_H
#define CPU_ADD_H

double add_double_double(double a, double b) {return (a+b);}
double add_int_double(int a, double b) {return ((double)(a)+b);}
int   add_int_int(int a, int b) {return (a+b);}

#endif

Моя цель - реализовать следующие функции (их объявления и функциональность вы можете найти в poly_subtype.h выше):

Number& IntClass::addInt(IntClass& x);
Number& IntClass::addDouble(DoubleClass& x);
Number& IntClass::operator+(Number& x);
Number& DoubleClass::addInt(IntClass& x);
Number& DoubleClass::addDouble(DoubleClass& x);
Number& DoubleClass::operator+(Number& x);

Надеюсь, теперь стало понятнее.

Например, AddInt :

Number& IntClass::addInt(IntClass& x){
 int num = add_int_int(my_number, x.get_number());
 IntClass* a = new IntClass(num);
 IntClass &ref = *a;
 return ref;
}

Ответы [ 4 ]

4 голосов
/ 08 января 2011

Ваш пример кода является утечкой памяти, ожидающей, чтобы произойти. Кто несет ответственность за удаление объекта после его завершения? Тот факт, что вы возвращаете ссылку (а не указатель), делает еще менее очевидным, что объект был размещен в куче. В какой-то момент кому-то нужно будет сделать delete &obj;, что довольно извращенно.

Как правило, вы должны возвращать только ссылки на объекты, на которые ссылаются в другом месте (например, члены класса или объекты кучи, на которые указывают члены класса). В вашем конкретном случае вам, вероятно, лучше сделать что-то вроде:

IntClass myFunc()
{
    ...
    return IntClass(10);
}

т.е. вернуться по значению.

3 голосов
/ 08 января 2011

Почему вы хотите вернуть ссылку в первую очередь?Просто возвращайте значения вместо ссылок.Компилятор, как правило, оптимизирует удаление копии, если вас это беспокоит.

См. Effective C ++, Item 21.

1 голос
/ 08 января 2011

О, теперь я вижу. Предполагается, что вы реализуете мутирующую операцию, которая модифицирует этот объект и возвращает ссылку на него. Так это как:

Number& YourNumber::Add(const YourNumber& pX) {
 // do addition which mutates this...
 return *this;
}
0 голосов
/ 08 января 2011

Хотя вы можете сделать что-то, как вы написали выше, это плохо.Если ресурс размещен в бесплатном хранилище, вы должны вернуть указатель на него, а не ссылку.Более того, используйте умный указатель соответствующего вида: например, std::auto_pointer (или лучше std/boost::unique_ptr), если ресурс не удерживается производителем, и std::shared_ptr, если имеет место обратное.Ваш пример кода допустим, но потребитель возвращенной ссылки не знает (и не может), как обращаться с возвращенной ссылкой.

Я могу представить себе возвращение постоянной ссылки на объект в сценарии, подобном следующему:

class Producer {
 std::shared_ptr<SomeObject> mObject;

public:
 Producer() : mObject(new SomeObject) {}

 const SomeObject& GetObject() const {
  return *mObject;
 }

};

Однако вы можете вернуть ссылку на объект со статической продолжительностью, что имеет определенные недостатки - выне имеют (соответствующего) контроля над временем жизни объекта., например:

SomeObject& GetSomeObjectSingletonReference() {
 static SomeObject sInstance;
 return sInstance;
}

Приветствия,

Пол

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...