【发布时间】:2021-02-06 18:52:11
【问题描述】:
我们正在创建一个旨在从当前模块发送信息的类(细节与这个问题无关)。这种类型的对象被创建并填充了需要发送的部分数据,然后传递给(不同的类)成员函数。该函数为对象提供其余数据,然后通过对象本身的调用触发发送。因为传入的信息是动态的,所以信息传输对象是一个临时对象,是用最新数据创建的。我们列出的设计在下面的精简源代码中,但 gcc/C++ 不允许这样做,并给出显示的错误。
问题是,我们如何使用可以被调用函数修改和使用的临时对象(避免内存泄漏)来完成预期的行为?
gcc 编译器错误:
infoxfer.cpp: In function ‘int main()’:
infoxfer.cpp:54:43: error: cannot bind non-const lvalue reference of type ‘XferInfo&’ to an rvalue of type ‘XferInfo’
51 | callee.doSomething("Something param", XferInfo("from main()"));
| ^~~~~~~~~~~~~~~~~~~~~~~
infoxfer.cpp:36:62: note: initializing argument 2 of ‘void Callee::doSomething(const string&, XferInfo&)’
33 | void doSomething(const string& somethingParam, XferInfo& xferInfo)
| ~~~~~~~~~~^~~~~~~~
提炼的示例代码:
infoxfer.cpp:
#include <iostream>
using std::cout;
using std::endl;
#include <string>
using std::string;
class XferInfo
{
private:
const string mCallerInfo;
string mCalleeInfo;
public:
XferInfo(const string& callerInfo) : mCallerInfo(callerInfo)
{}
void setCalleeInfo(const string& calleeInfo)
{
mCalleeInfo = calleeInfo;
}
void sendData()
{
// simulate sending data
cout << mCallerInfo << " | " << mCalleeInfo << endl;
}
};
class Callee
{
public:
void doSomething(const string& somethingParam, XferInfo& xferInfo)
{
// complete data for xfer
xferInfo.setCalleeInfo(somethingParam);
// simulate doing something
cout << "do something" << endl;
// send the complete info
xferInfo.sendData();
}
};
int main()
{
cout << "start" << endl;
Callee callee;
callee.doSomething("Something param", XferInfo("from main()"));
cout << "end" << endl;
return 0;
}
【问题讨论】:
-
为什么不简单地按值传递 XferInfo?或者使用右值引用。看来左值引用确实不是您想要的。
-
“使用临时对象(避免内存泄漏很好)”你似乎在这里混淆了概念。内存泄漏很糟糕,但悬空引用同样糟糕(或更糟)。如果按值复制,对象的生命周期将被限制在变量的范围内。没有内存泄漏。
-
将
callee.doSomething("Something param", XferInfo("from main()"));更改为XferInfo info("from main()"); callee.doSomething("Something param", info); -
编译器必须创建一个
XferInfo对象somewhere。按值传递它可以很好地包装它并避免其他潜在问题。
标签: c++ gcc pass-by-reference temporary-objects lvalue-to-rvalue