我在下面的第二行收到错误“返回临时引用”。
class Object : public std::map <ExString, AnotherObject> const {
public:
const AnotherObject& Find (const ExString& string ) const {
Object::const_iterator it = find (string);
if (it == this->end()) { return AnotherObject() };
return ( it->second );
}
}
我的类实现了std :: map。
我是C ++的新手,所以我猜它只是一个语法错误。有什么帮助吗?
答案 0 :(得分:15)
如果你的功能如下:
AnotherObject& getAnotherObject()
{
. . .
Object::const_iterator it = find ("lang");
if (it == this->end()) { return AnotherObject() };
. . .
}
问题是,一旦函数退出,你返回的AnotherObject()将被销毁,因此函数的调用者将引用一个虚假对象。
如果您的函数按值返回:
AnotherObject getAnotherObject()
然后在原件被销毁之前制作一份副本,你就可以了。
答案 1 :(得分:7)
return AnotherObject();
创建一个在函数退出之前被销毁的对象 - 临时对象在包含它们[*]的表达式的末尾被销毁,而表达式AnotherObject()
创建一个临时对象。
由于函数通过引用返回,这意味着调用者甚至有机会看到该引用,它不再引用有效对象。
如果函数是按值返回的,那就没关系了,因为临时函数会被复制[**]。
[*]有几种情况没有,但他们在这里没有帮助。
[**]实际上有一个称为“复制构造函数省略”的优化,这意味着不需要创建,复制和销毁临时版本。相反,在某些条件下,允许编译器以与 创建临时文件相同的方式创建副本的目标,而不是打扰临时文件。
答案 2 :(得分:3)
您正在堆栈AnotherObject()
上创建一个临时值,并在它被销毁之前将其返回。你的函数的调用者会得到垃圾,所以它被禁止了。
也许你想在堆上分配它并返回指向它的指针?
return new AnotherObject();
或者,声明你的函数将“副本”返回给你的对象,而不是像我假设你现在正在返回的引用:
AnotherObject f()
{
return AnotherObject(); // return value optimization will kick in anyway!
}
答案 3 :(得分:1)
必须声明该函数以返回引用,并且引用必须引用在函数退出后将继续存在的对象。您的临时“AnotherObject()”在返回后立即被破坏,因此显然无效。如果无法更改方法签名,则可能需要抛出异常而不是返回错误值。
答案 4 :(得分:1)
您应该从“AnotherObject&amp;”更改函数的返回类型到“AnotherObject”并按值返回该对象。否则就会像Blindy描述的那样
答案 5 :(得分:0)
对AnotherObject的构造函数的调用会在堆栈上创建一个新实例,当该方法返回时,该实例立即被销毁。
如果查找失败,创建和返回新对象很可能不是一个好主意。调用代码无法判断返回的对象是否是数据结构中存在的先前存在的对象。
如果您确实想这样做,那么您应该将新对象添加到数据结构中,然后返回指向数据结构中新对象的迭代器。
这样的事情:
if (it == this->end()) {
it = this->insert(pair<ExString, AnotherObject>( string, AnotherObject() ));
return it->second;
}
答案 6 :(得分:0)
您不应该返回对在行尾销毁的临时引用的引用,也不应该引用在函数末尾销毁的本地引用。
如果要保留当前签名,则必须添加一个静态常量实例,您可以将其作为默认值返回。
#include <iostream>
template <class T>
class X
{
T value;
static const T default_instance;
public:
X(const T& t): value(t) {}
const T& get(bool b) const
{
return b ? value : default_instance;
}
};
template <class T>
const T X<T>::default_instance = T();
int main()
{
X<int> x(10);
std::cout << x.get(true) << ' ' << x.get(false) << '\n';
}
您也可以按值返回或返回指针,在这种情况下您可以返回NULL。
答案 7 :(得分:0)
我个人认为这有点像黑客攻击,但只要你真正坚持返回引用的常量,你就应该能够返回一个静态构造的AnotherObject实例,它只是“raison d'etre” “是你的功能的”未找到“返回值。例如,使它成为类Object的静态const私有成员,只要AnotherObject的默认构造实例不是要包含在Object实例中的有效值,就应该没问题。