在main函数中,我以两种方式调用函数send。我想知道两者之间有什么区别。调用哪些构造函数,如何在两种情况下复制数据?当我第一次调用它时,我得到了不同的send数据值。当我为OneClass(OneClass *)删除内联时,它得到了解决。
#include <iostream>
class OneClass{
const void *data;
public:
inline OneClass(const void *inData);
OneClass(const OneClass &in){
data = in.data;
}
static OneClass create(const unsigned &in);
void send();
};
OneClass OneClass::create(const unsigned &in){
return OneClass(&in);
}
inline OneClass::OneClass(const void *inData):data(inData){
}
void OneClass::send(){
std::cout<<"send: "<<*((int*)data)<<"\n";
}
main()
{
int var = 100;
OneClass one = OneClass::create(var);
one.send();//I get different value than 100 in cout(On windriver 64bit)
OneClass::create(var).send();
}
答案 0 :(得分:4)
调用哪些构造函数和复制的内容无关紧要。你有未定义的行为。内联声明也无关紧要,它恰好是改变未定义行为的东西。
未定义行为的原因在于:
OneClass OneClass::create(const unsigned &in){
return OneClass(&in); // <-- here you take the address of the referenced integer
}
好的,所以你拿一个对象的地址。为什么那么糟糕?因此:
OneClass::create(100);
整数文字绑定到引用in
。将文字绑定到引用(必须为const
)时,会创建临时文件。调用create
后,临时对象不再存在。地址存储在成员变量中,稍后使用它会导致未定义的行为。
然而,在第二种情况下:
OneClass::create(100).send();
在创建临时表达的同一个完整表达式中调用send()
。因此临时仍然存在,并且对象内的指针仍然有效,并且您不会得到未定义的行为。
由于OneClass
的实例存储了对象的地址,因此必须确保其存储的地址的任何对象存在的时间长于实例。您应该将create
的参数类型更改为指针,以便调用者知道发生了什么并且不会尝试传递文字。
修改:更新
如果参数是int
变量而不是文字,则上述内容仍然适用,因为int
绑定到const unsigned&
时会创建临时变量。如果您将参数类型更改为const int&
,并且在使用指针时使用了范围内的变量,那么将定义行为。