创建一个新对象并传入方法参数
Creating a new object and passing in method parameter
在Java中,我们可以创建一个新对象,并在其参数范围内将其传递给方法,如下所示:
wrapper.set_state( new Medium() );
在C++中与此等价的是什么?我想我可以在之前创建对象,然后传递它,但能够在参数中创建它似乎会更整洁。
在Java 中
wrapper.set_state( new Medium() );
创建一个新的、引用计数的Medium实例,并通过引用将其传递给包装器的set_state函数。
在C++中,上述代码在技术上是有效的,在包装类中,set_state将被定义为:
void set_state(Medium* medium);
但您要做的是将一个非引用计数指针传递给Medium的新实例。您将负责确保在第1天之后是CCD_。如果所有的set_state都是这样的:
void set_state(Medium* medium)
{
this->medium = medium;
}
每次对setstate进行第二次调用时,都会引入内存泄漏。在C++中,当覆盖像这样的原始指针时,没有引用计数。如果没有人再指向分配,则分配将丢失/泄漏。
您可能更喜欢通过引用传递对象:
void set_state(const Medium& medium)
{
this->medium = medium; // copy
}
通过:调用
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
尽管这是一个副本,但在某些情况下,编译器能够消除其中一个副本(请参阅http://ideone.com/gNICYt)
如果你绝对需要使用指针(有几个东西会引用完全相同的Medium实例),你可能需要考虑使用std::shared_ptr
,它提供了引用计数。
#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;
}
在C++中与此等价的是什么?
有多种类似的方法可以在c++中实现引用的Java语句。假设函数需要一个指针,那么完全相同的语法恰好是有效的c++。您必须考虑是否需要将指向手动分配对象的原始指针传递给函数。这很可能是不可取。
在c++中创建新对象的最简单方法是创建一个临时对象。创建临时并将其传递给函数的类似语法是:
wrapper.set_state(Medium());
因为Java引用是被计算在内的,所以语义上最接近的类似方法(可能可以说)是传递std::shared_ptr<Medium>
。但是,因为在c++中,与Java不同,您可以选择值语义,但另一方面,您没有垃圾收集,所以您不能假设您实际上应该具有相同的语义。
等价的是,但可能不相同的结果:
#include <iostream>
#include <memory> // c++11
class Helper {
public:
Helper () { std::cout << "Helper says hin"; }
void Speak() { std::cout << "Helper says barkn"; }
~Helper () { std::cout << "Helper says byen"; }
};
class Message {
public:
Message (Helper* h, bool freeme = false) {
std::cout << "Message says hi..btw you have a memory leakn";
h->Speak();
if (freeme) {
std::cout << "Message says nice onen";
delete h;
}
}
Message (std::unique_ptr<Helper> h) {
std::cout << "Message say hin";
h->Speak();
}
~Message () {
std::cout << "Message says byen";
}
};
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;
}
这取决于参数的类型,请考虑以下内容:
- 值参数:
void set_state(Medium)
move用临时初始化,即使用set_state(Medium())
- Rvalue引用参数:
void set_state(Medium&&)
,绑定它引用一个新建的临时,即使用set_state(Medium())
(这与value参数的情况语法相同,但语义略有不同) - Lvalue引用参数:
void set_state(Medium&)
,将对新分配对象的引用传递给它,即使用set_state(*new Medium())
- 指针参数:
delete
0,向它传递一个指向新分配对象的指针,即使用set_state(new Medium())
如果参数类型具有任何const
或volatatile
修饰符,以及如果参数是用Medium
的非模糊基类型声明的,则同样适用
注意:使用new
时要小心,与Java不同,C++不需要自动垃圾收集,因此您需要确保在不再需要对象时而不是以前删除该对象。(最安全的方法是不delete
您的对象,但这只会浪费内存)
另一点需要注意的是,由于C++与Java(在语义方面)非常不同,我建议阅读一本关于该语言的好书或其他资源,而不是对你不理解的一切提出问题,因为这样你可能会错过一些重要的差异,并产生灾难性的结果。
- c++方法参数只能在linux的发布模式下自行更改
- 使用移动语义:右值引用作为方法参数
- 无法将动态创建的对象数组从 qml 发送到 c++ 作为方法参数
- 将方法参数类型更改为子类中的派生类
- ofstream作为C 中的方法参数
- 使用 gmock 匹配器将 std::function 设置为 EXPECT_CALL 中的方法参数
- C com 方法参数扣除
- 获取非静态方法参数计数
- 使用 gmock 返回模拟方法参数
- 运行 QML 时出现"未知方法参数类型"错误
- 基本C - 构造contaning对象引用,并将其作为方法参数传递
- 将C 方法参数转换为模板参数会因编译错误而失败
- 如何在方法参数中使用boost :: asio :: buffer
- qsharedPointer作为方法参数或方法的返回值的良好实践
- 如何将方法指针声明为Typedef方法参数
- 方法参数中的 OpenCV 垫"预期")""
- 方法参数中的 consst* 常量
- 带有“class”详细类型说明符的方法参数
- 具有原始方法参数派生类的 C++ 重载方法参数
- C++ std::string length() 或 size() 不适用于方法参数