开发者

How to return a reference in C++

If for example I create a new object in a function and I want to return its reference how can I do it?

Lets say I got an IntClass that has a 'int num' field in the private. So i want to create a new element of IntClass in the function and return the reference of that object. I've tried something like that but it seems illegal (from some reason when I do such thing the Binaries gets deleted when I compile the code although I get no errors from the compiler itself (ECLIPSE):

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

Any ideas how to return a reference then?

EDIT: It's allowed to "assume" that C++ uses a Garbage-Collection

As it's not clear to most of you WHY I "want" to do it so here is the full question:

I got this file (Not made by me and can't be edited):

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 <<开发者_JAVA技巧; 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

and I've got this file (again, not written by me and can't be edited - says I can use those functions but not the '+' operator.

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

My goal is to implement the next functions (which you can find their declarations and functionality in poly_subtype.h above):

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

I hope it's more clear now.

For example, 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;
}


Why do you want to return a reference in the first place? Just return values instead of references. The compiler usually optimizes the copy away, if that's your concern.

See Effective C++, Item 21.


Your example code is a memory-leak waiting to happen. Who is responsible for deleting the object when it's finished? The fact that you return a reference (rather than a pointer) makes it even less apparent that an object has been allocated on the heap. At some point, someone would need to do delete &obj;, which is pretty perverse.

In general, you should only return references to objects that are referred to elsewhere (e.g. class members, or heap objects that are pointed to by class members). In your particular case, you're probably best to do something like:

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

i.e. return-by-value.


Oh, I see now. You are supposed to implement a mutating operation which modifies 'this' object a returns a reference to it. So it's like:

Number& YourNumber::Add(const YourNumber& pX) {
 // do addition which mutates this...
 return *this;
}


While you can do something like you wrote above, it is considered bad style. If a resource is allocated on the free-store you should return a pointer to it, not a reference. Even better, use a smart pointer of the appropriate kind: e.g. std::auto_pointer (or better std/boost::unique_ptr) if the resource is not held by the producer and std::shared_ptr if the opposite is the case. Your code example is legal, but the consumer of the returned reference does not (and cannot) know how to deal with the returned reference.

I can imagine returning a constant reference to an object in a scenario like this:

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

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

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

};

You could however return a reference to an object with static duration, which has certain drawbacks though - you do not have (appropriate) control over the lifetime of the object, for example:

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

Cheers,

Paul

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜