データを保存するObjectというクラスがあります。
次のような関数を使用して、参照で返したいと思います。
Object& return_Object();
次に、私のコードでは、次のように呼び出します。
Object myObject = return_Object();
このようなコードを記述し、コンパイルします。ただし、コードを実行すると、一貫してセグフォールトが発生します。参照によってクラスオブジェクトを返す適切な方法は何ですか?
おそらくスタック上にあるオブジェクトを返しているでしょう。つまり、return_Object()
はおそらく次のようになります。
Object& return_Object()
{
Object object_to_return;
// ... do stuff ...
return object_to_return;
}
これがあなたがしていることなら、あなたは運が悪い-object_to_return
は範囲外になり、return_Object
の終わりに破壊されたので、myObject
は非-既存のオブジェクト。値で返すか、より広いスコープで宣言されたObject
を返すか、ヒープにnew
edを返す必要があります。
使用できるのは
Object& return_Object();
返されるオブジェクトのスコープが関数よりも大きい場合。たとえば、カプセル化されたクラスがある場合に使用できます。関数でオブジェクトを作成する場合は、ポインターを使用します。既存のオブジェクトを変更する場合は、引数として渡します。
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;
}
};
参照によってローカル以外のオブジェクトのみを返すことができます。デストラクタは、内部ポインタなどを無効にしている可能性があります。
値を返すことを恐れないでください- 高速です !
まあ、それはコードでは本当に美しい解決策ではないかもしれませんが、関数のインターフェースでは本当に美しいです。また、非常に効率的です。 2番目の方がより重要な場合(たとえば、ライブラリを開発している場合)に理想的です。
トリックはこれです:
A a = b.make();
は、Aのコンストラクターに内部的に変換されます。つまり、A a(b.make());
を記述したかのように変換されます。b.make()
は、コールバック関数を含む新しいクラスになります。これが私の最小限の例です。わかりやすいように、main()
のみをチェックしてください。内部はそうではありません。
速度の観点から: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;
}
いくつか例を示します。
const string &mainip(const string &s)
{
string ret=s;
// operator ret
return ret;
}
retは最後に破棄されるため、retを参照で返すことはできません。
const string &shorterString(const string &s1,const string &s2)
{
return s1.size()<s2.size()?s1:s2;
}
s1とs2の両方の参照がまだ存在している場合に戻ります。
char &get_val(string &str,string::size_type ix)
{
return str[ix];
}
以下の使用コード:
string s("123456");
cout<<s<<endl;
char &ch = get_val(s,0);
ch ='A';
cout<<s<<endl; // A23456
参照による戻りの後、オブジェクトはまだ存在しているためです。
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;
}
使用例:
Student stu;
stu.m_name = 'jack';
string name = stu.getName(); //
//or
string name2 = Test(stu);
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;
}