创建一个新对象并传入方法参数

时间:2016-05-01 22:47:27

标签: c++ oop methods parameters instantiation

在Java中,我们可以创建一个新对象并将其传递给参数中的方法,如下所示:

wrapper.set_state( new Medium() );

C ++中与此相同的是什么? 我想我之前可以创建对象然后传递它,但是能够在参数中创建它看起来更整洁。

4 个答案:

答案 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())
  • Rvalue-reference parameter:void set_state(Medium&&),绑定它以引用新构造的临时,即使用set_state(Medium())(这与value参数的语法相同,但语义略有不同)
  • 左值参考参数:void set_state(Medium&),将其传递给新分配的对象,即使用set_state(*new Medium())
  • 指针参数:void set_state(Medium*),将指针传递给新分配的对象,即使用set_state(new Medium())

如果参数类型具有任何constvolatatile修饰符,并且参数声明的类型为非ambigiouse基类型Medium,则同样适用

注意:使用new时要小心,与Java不同,C ++不需要自动垃圾回收,因此您需要确保在不再需要时而不是之前删除该对象。 (最安全的事情就是不要delete你的物体,但这只会浪费记忆力)

另一个注意事项,因为C ++与Java非常不同(在语义学术语中)我建议阅读一本好书或其他有关该语言的资源,而不是询问有关你不理解的所有事情的问题,因为你会可能会错过这种方式的一些重要差异,并带来灾难性的后果。