12

我刚刚学习 C++,遇到了以下难题:

作为一个 C++ 新手,我读过使用引用而不是指针(如果可能的话)通常是一个好主意,所以我试图尽早养成这个习惯。结果,我有很多具有一般形式的方法

void myMethod(ParamClass const& param);

现在,我想知道调用这些方法的最佳方法是什么。当然,每个调用都需要一个不同的对象作为参数传递,据我所知,创建它的唯一方法是 new 运算符,所以现在我正在执行以下操作:

myObject.myMethod(*new ParamClass(...));

虽然这种方法完全有效,但我想知道是否没有另一种已经建立的“c++ 方式”来做到这一点。

谢谢您的帮助!担

4

6 回答 6

14

你应该尽量不要使用new, 因为使用它会带来内存管理的麻烦。

对于您的示例,只需执行以下操作:

int main(int, char*[])
{
  SomeObject myObject;

  // two phases
  ParamClass foo(...);
  myObject.myMethod(foo);

  // one phase
  myObject.myMethod(ParamClass(...));

  return 0;
}

我推荐第一种方法(两次),因为第二种方法有一些微妙的问题。

编辑:评论并不适合描述我所指的陷阱。

如前所述@Fred Nurk,该标准对临时人员的生命周期做了一些说明:

[类.临时]

(3) 临时对象被销毁作为评估完整表达式 (1.9) 的最后一步,该完整表达式 (从词法上) 包含它们被创建的点。即使评估以抛出异常结束也是如此。销毁临时对象的值计算和副作用仅与完整表达式相关联,与任何特定子表达式无关。

(5) 引用所绑定的临时对象或引用所绑定的子对象的完整对象的临时对象在引用的整个生命周期内都将持续存在 [注意:除了在某些情况下...]

(5) [例如...] 在函数调用 (5.2.2) 中对引用参数的临时绑定一直持续到包含该调用的完整表达式完成为止。

这可能导致两个细微的错误,大多数编译器都没有捕捉到:

Type const& bound_bug()
{
  Type const& t = Type(); // binds Type() to t, lifetime extended to that of t
  return t;
} // t is destroyed, we've returned a reference to an object that does not exist

Type const& forwarder(Type const& t) { return t; }

void full_expression_bug()
{
  T const& screwed = forwarder(T()); // T() lifetime ends with `;`
  screwed.method(); // we are using a reference to ????
}

Argyrios 应我的要求对 Clang 进行了修补,以便它检测到第一种情况(实际上还有一些我最初没有想到的情况)。forwarder但是,如果实施不是内联的,则第二个可能很难评估。

于 2011-02-01T13:49:50.920 回答
3

尝试: myObject.myMethod(ParamClass(...)); 在 C++ 中,与 Java 不同,您并不总是需要说new要创建一个新对象。

于 2011-02-01T13:48:47.100 回答
1

既定的方法是使用自动局部变量:

ParamClass myParam;
myOjbect.myMethod(myParam);

通过以new您的方式使用,您正在产生内存泄漏。一旦函数返回,什么都不会处理该对象 - C++ 不像其他一些语言那样具有垃圾收集。

于 2011-02-01T13:49:30.763 回答
0

您需要了解对象的生命周期。如果传递*new ParamClass给函数,则将新对象的所有权授予该函数。如果函数没有破坏它(并且它不应该在给出引用的情况下这样做),你会得到内存泄漏。

相反,您应该这样做:

ParamClass myParamClass(...);
myObject.myMethod(myParamClass);
于 2011-02-01T13:51:28.363 回答
0

当你写

myObject.myMethod(*new ParamClass(...)); 

你失去了指向新对象的指针。也就是说,这将起作用,但您将无法稍后delete处理该对象。所以你可以这样做:

ParamClass pc(...);
myObject.myMethod(pc);

或者,更容易

myObject.myMethod(ParamClass(...));

或者,如果出于某种莫名其妙的原因需要动态分配

ParamClass* pPc = new ParamClass(...);
myObject.myMethod(*pPc);
...
delete pPc;

或者,使用智能指针来避免手动删除。就像是:

boost::scoped_ptr<ParamClass> spPc(new ParamClass(...));
myObject.myMethod(*pPc);

希望这可以帮助

于 2011-02-01T13:54:56.923 回答
0

请注意,将先前创建的对象(我的意思是用户定义类的对象)的值分配给 java 和 c++ 中的新对象之间存在很大差异,大约是:

1- 在 C++ 中:object new =(object) old [创建一个从旧到新的对象的副本,当你修改更新时,旧的不会改变!]

2-在java中:object new =(object) old [创建对旧对象的引用,当你修改新对象时,旧对象也会改变(非常重要)]

结论 :

在 java 中:“object new =(object) old”与 c++ 中的“object &new =(object) old”相同。

于 2013-08-23T13:50:40.897 回答