如何在 C++ 中通过引用返回类对象?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8914509/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to return a class object by reference in C++?
提问by user788171
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?
我已经编写了这样的代码并且它可以编译。但是,当我运行代码时,我始终遇到段错误。通过引用返回类对象的正确方法是什么?
回答by Chowlett
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 new
ed onto the heap.
如果这是您正在做的事情,那么您就不走运了 -object_to_return
已经超出范围并在 结束时被破坏return_Object
,因此myObject
引用了一个不存在的对象。您要么需要按值返回,要么返回一个Object
在更广泛范围内声明的或new
ed 到堆上。
回答by UmNyobe
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;
}
};
回答by spraff
回答by Jayhello
I will show you some examples:
我将向您展示一些示例:
First example, do not return local scope object, for example:
第一个例子,不返回局部作用域对象,例如:
const string &dontDoThis(const string &s)
{
string local = s;
return local;
}
You can't return local
by reference, because local
is destroyed at the end of the body of dontDoThis
.
您不能通过local
引用返回,因为local
在dontDoThis
.
Second example, you can return by reference:
第二个例子,你可以通过引用返回:
const string &shorterString(const string &s1, const string &s2)
{
return (s1.size() < s2.size()) ? s1 : s2;
}
Here, you can return by reference both s1
and s2
because they were defined before shorterString
was called.
在这里,您可以通过引用返回s1
,s2
因为它们是在shorterString
调用之前定义的。
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
get_val
can return elements of s
by reference because s
still exists after the call.
get_val
可以s
通过引用返回元素,因为s
调用后仍然存在。
Fourth example
第四个例子
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;
}
usage example:
用法示例:
Student student;
student.m_name = 'Hyman';
string name = student.getName();
// or
string name2 = Test(student);
Fifth example:
第五个例子:
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;
}
You could then use the operator=
above like this:
然后你可以operator=
像这样使用上面的:
String a;
String b;
String c = b = a;
回答by peterh - Reinstate Monica
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:
诀窍是这样的:
- A line
A a = b.make();
is internally converted to a constructor of A, i.e. as if you had writtenA a(b.make());
. - Now
b.make()
should result a new class, with a callback function. - This whole thing can be fine handled only by classes, without any template.
- 一行
A a = b.make();
在内部被转换为 A 的构造函数,即就像你写了A a(b.make());
. - 现在
b.make()
应该产生一个带有回调函数的新类。 - 这整个事情只能由类处理,没有任何模板。
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;
}