我只是在学习C ++,而且我遇到了以下难题:
作为一名C ++新手,我读过使用引用而不是指针(如果可能的话)通常是一个好主意,所以我想尽早养成这个习惯。因此,我有很多具有
一般形式的方法void myMethod(ParamClass const& param);
现在,我想知道调用这些方法的最佳方法是什么。当然,每个调用都需要一个不同的对象作为参数传递,据我所知,创建它的唯一方法是new运算符,所以现在我正在做以下事情:
myObject.myMethod(*new ParamClass(...));
虽然这种方法完全有效,但我想知道是否还没有其他已经建立的“c ++方法”。
感谢您的帮助! 丹
答案 0 :(得分:13)
您应该尽量不要使用new
,因为使用它会带来内存管理的麻烦。
对于您的示例,请执行以下操作:
int main(int, char*[])
{
SomeObject myObject;
// two phases
ParamClass foo(...);
myObject.myMethod(foo);
// one phase
myObject.myMethod(ParamClass(...));
return 0;
}
我推荐第一种方法(两次),因为第二种方法存在微妙的问题。
编辑:评论不适合描述我所指的陷阱。
正如@Fred Nurk
所引用的那样,该标准说明了有关临时生命的一些事情:
<强> [class.temporary] 强>
(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
的实现不是内联的,那么第二个可能很难评估。
答案 1 :(得分:3)
尝试:
myObject.myMethod(ParamClass(...));
在C ++中,与Java不同,您并不总是需要说new
来创建新对象。
答案 2 :(得分:1)
确定的方法是使用自动局部变量:
ParamClass myParam;
myOjbect.myMethod(myParam);
以你的方式使用new
,你会产生内存泄漏。一旦函数返回,什么都不会处理该对象--C ++没有像其他语言那样进行垃圾收集。
答案 3 :(得分:0)
您需要了解对象的生命周期。如果将*new ParamClass
传递给函数,则会将新对象的所有权授予该函数。如果函数没有销毁它(并且在给定引用的情况下它永远不应该这样做),你将会出现内存泄漏。
相反,你应该这样做:
ParamClass myParamClass(...);
myObject.myMethod(myParamClass);
答案 4 :(得分:0)
写作时
myObject.myMethod(*new ParamClass(...));
你丢失了指向new'd对象的指针。也就是说,这将有效,但您将无法在以后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);
希望这有帮助
答案 5 :(得分:0)
请注意,在java和c ++中将先前创建的对象的值(我的意思是用户定义的类的对象)分配给新对象之间存在很大差异 ,它是关于:
1- C ++ :对象new =(对象)较旧[创建较旧较旧的对象的副本,当您修改较新的对象时,旧的 将不会 改变!]
2- in java :object new =(object)older [创建对旧对象的引用,当您修改较新的对象时,较旧的 将 改变(非常非常重要)]
结论:
java中的:“object new =(object)older”与c ++中的“object&amp; new =(object)old”相同。