C ++中对象实例化的方法访问

时间:2015-11-25 12:08:16

标签: c++ inline

在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();

}

1 个答案:

答案 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&,并且在使用指针时使用了范围内的变量,那么将定义行为。