在Java中,我们可以创建一个新对象并将其传递给参数中的方法,如下所示:
wrapper.set_state( new Medium() );
C ++中与此相同的是什么? 我想我之前可以创建对象然后传递它,但是能够在参数中创建它看起来更整洁。
答案 0 :(得分:4)
在Java中
wrapper.set_state( new Medium() );
创建一个新的,引用计数的Medium实例,并通过引用将其传递给包装器的set_state函数。
在C ++中,上面的代码在技术上是有效的,在你的包装类中,set_state将被定义为:
void set_state(Medium* medium);
但是你要做的是将一个非引用计数指针传递给一个新的Medium实例。您将负责确保delete
之后void set_state(Medium* medium)
{
this->medium = medium;
}
。如果所有set_state都这样做:
void set_state(const Medium& medium)
{
this->medium = medium; // copy
}
每次第二次调用set_state时,都会引入内存泄漏。在C ++中,当您覆盖这样的原始指针时,没有引用计数。如果没有人再指向分配,则分配将丢失/泄露。
您可能更喜欢通过引用传递对象:
Medium m;
// populate m
wrapper.set_state(m);
// or
wrapper.set_state(Medium());
通过:
调用void set_state(Medium medium)
{
this->medium = medium; // copy
}
// invocation:
Medium m;
// populate m
wrapper.set_state(m); // copy
或者您可以通过值传递:
std::shared_ptr
虽然这是副本,但在某些情况下编译器可以省略其中一个副本(参见http://ideone.com/gNICYt)
如果你绝对需要使用指针(有几件事将引用完全相同的Medium实例),你可能需要考虑使用提供引用计数的#include <memory>
struct Medium {};
class Wrapper {
std::shared_ptr<Medium> medium;
public:
void set_state(std::shared_ptr<Medium> medium) {
this->medium = medium; // if we'd called it m_medium, or medium_
// we could just have written
// m_medium = medium; or medium_ = medium;
}
};
int main(void) {
Wrapper w;
w.set_state(std::make_shared<Medium>());
return 0;
}
。
NOT NULL
答案 1 :(得分:1)
在C ++中与此相同的是什么?
在c ++中实现引用的Java语句有多种类似的方法。假设函数期望指针,完全相同的语法实际上是有效的c ++。是否需要传递给函数,指向手动分配的对象的原始指针是您必须考虑的事情。它很可能不是可取的。
在c ++中创建新对象的最简单方法是创建一个临时对象。创建临时函数并将其传递给函数的类似语法是:
wrapper.set_state(Medium());
因为计算了Java引用,所以语义上最接近的模拟(可能可以说)是传递std::shared_ptr<Medium>
。但是,因为在c ++中不像Java,你可以选择值语义,但另一方面,你没有垃圾收集,你不能假设你实际上应该有相同的语义。
答案 2 :(得分:0)
等同于是,但结果可能不一样:
#include <iostream>
#include <memory> // c++11
class Helper {
public:
Helper () { std::cout << "Helper says hi\n"; }
void Speak() { std::cout << "Helper says bark\n"; }
~Helper () { std::cout << "Helper says bye\n"; }
};
class Message {
public:
Message (Helper* h, bool freeme = false) {
std::cout << "Message says hi..btw you have a memory leak\n";
h->Speak();
if (freeme) {
std::cout << "Message says nice one\n";
delete h;
}
}
Message (std::unique_ptr<Helper> h) {
std::cout << "Message say hi\n";
h->Speak();
}
~Message () {
std::cout << "Message says bye\n";
}
};
int main()
{
{ Message msg1(new Helper); } // warning: leak
std::cout << "--- 1 ---\n";
{ Message msg2(std::unique_ptr<Helper>(new Helper));}
std::cout << "--- 2 ---\n";
{ Message msg3(new Helper); } // warning: leak
std::cout << "--- 3 ---\n";
{ Message msg3(new Helper, true); }
return 0;
}
答案 3 :(得分:-1)
这取决于参数的类型,请考虑以下内容:
void set_state(Medium)
使用临时值初始化它,即使用set_state(Medium())
void set_state(Medium&&)
,绑定它以引用新构造的临时,即使用set_state(Medium())
(这与value参数的语法相同,但语义略有不同) void set_state(Medium&)
,将其传递给新分配的对象,即使用set_state(*new Medium())
void set_state(Medium*)
,将指针传递给新分配的对象,即使用set_state(new Medium())
如果参数类型具有任何const
或volatatile
修饰符,并且参数声明的类型为非ambigiouse基类型Medium
,则同样适用
注意:使用new
时要小心,与Java不同,C ++不需要自动垃圾回收,因此您需要确保在不再需要时而不是之前删除该对象。 (最安全的事情就是不要delete
你的物体,但这只会浪费记忆力)
另一个注意事项,因为C ++与Java非常不同(在语义学术语中)我建议阅读一本好书或其他有关该语言的资源,而不是询问有关你不理解的所有事情的问题,因为你会可能会错过这种方式的一些重要差异,并带来灾难性的后果。