如何在C ++中创建对象?

时间:2012-07-29 17:42:25

标签: c++

我了解Java,但对C ++知之甚少。我正在尝试在https://developers.google.com/v8/get_started的代码的main函数中为前3个语句编写一个类。

首先,我对如何在C ++中创建对象有疑问。请参阅以下代码。

HandleScope handle_scope;
Persistent<Context> context = Context::New();
Context::Scope context_scope(context);

我认为在C ++中,当你声明一个类的变量时,就是一个在该点创建的类的实例。您不需要在Java中使用new关键字。因此,第一个语句将创建一个HandleScope实例,该实例将存储在handle_scope中。 现在我不明白第二个陈述是如何起作用的。根据我的知识,在=之前的部分将创建一个新的Persistent对象,可以通过变量context来引用它。然后Context :: New()将创建一个新对象并将其存储在上下文中?嗯,我知道我错了。但我根本不知道它会如何运作?

我正在尝试为上面写一个C ++类。这是我的尝试。

class MyClass {
private:
    HandleScope handle_scope;
    Persistent<Context> context;
    Context::Scope context_scope;

public:
    MyClass(); 
};

MyClass::MyClass()
{
    context = Context::New();
    context_scope = new Context::Scope(context);
}

我是否正确完成了初始化?

编辑:回复peachykeen(评论中) 我做了以下实验。

我写了一个Test类,如下所示。  测试     {     上市:         测试(){         cout&lt;&lt; “测试”&lt;&lt; ENDL;     }     };

在主要功能中我写了测试测试;它输出“Test”,表示在不使用new关键字的情况下创建对象。

4 个答案:

答案 0 :(得分:11)

你是对的,在C ++中,对象是在定义后立即创建的。您无需使用new关键字。

但是,与Java不同,可以使用不同类型的持续时间创建对象。使用new在堆上创建一个对象,动态存储持续时间:变量一直存在,直到您明确delete它为止。 (并且new返回指向创建对象的指针,以便您可以跟踪它)

如果您只是定义一个对象(如第一行和第三行),那么它将使用自动存储持续时间创建:也就是说,该对象一直存在,直到它超出范围。

这意味着您可以在函数内创建对象,并且保证一旦您离开函数它们将被销毁 - 无论如何你离开这个功能。无论您是返回还是抛出异常,所有具有自动存储持续时间的对象(不使用new创建)都可以保证正确清理。

这意味着您应该尽可能避免new。如果必须使用new,则通常应将结果指针包装到智能指针类中,该类是使用自动存储持续时间创建的对象,以便自动销毁它。然后,智能指针将自动调用新分配的对象上的delete,再次确保您不会泄漏内存。

这种区别是一个非常强大的工具,优秀的C ++程序员需要很好地理解。它是避免内存泄漏的关键,或者更普遍的是,各种资源泄漏,在某些方面,它比Java的垃圾收集器更强大。

例如,假设我们希望打开一个文件,然后将一些数据写入其中。在C ++中,我们可以这样做:

void foo() {
    std::ofstream file("foo.txt");
    doStuff(file); // call a function which does something with the file   
}

因为file是在没有使用new的情况下声明的,因为它有自动存储持续时间,我们保证它将拥有它的析构函数当它超出范围时调用,它将被正确清理 - 也就是说,流将被刷新,文件句柄将被关闭。

如果doStuff可能抛出异常并不重要。 无论我们如何离开foofile都会被正确销毁,因此我们不需要像try / finally那样混乱你会用Java。该类本身就是异常安全,无需用户做任何额外的努力。

尝试在Java中编写一个类似的代码段,保证,即使doStuff抛出异常,该文件也会立即关闭。它会更长,并且需要用户更多的关注。

答案 1 :(得分:0)

这将是等效的类:

class MyClass {
private:
    HandleScope handle_scope;
    Persistent<Context> context;
    Context::Scope context_scope;

public:
    MyClass(); 
};

MyClass::MyClass()
: context(Context::New()),
  context_scope(context)
{
}

当你写这样的陈述时:

Persistent<Context> context = Context::New();

您正在使用复制构造函数构建上下文。这与创建对象然后分配新值不同,尽管结果可能通常是等效的。

同样这句话:

Context::Scope context_scope(context);

正在构造context_scope并将上下文传递给构造函数。您可以使用构造函数初始化程序语法在类中获得等效行为,如我的示例所示。

答案 2 :(得分:0)

Persistent<Context> context = Context::New();

创建Persistent<Context>类型的对象,如果c-tor不明确,则从Context :: New的返回值初始化。

简单的例子。

#include <iostream>

class C
{
public:
    C(int)
    {
        std::cout << "C::C(int)" << std::endl;
    }
};

int main()
{
    C c = 1;
}

你的班级应该是

class MyClass {
private:
    HandleScope handle_scope;
    Persistent<Context> context;
    Context::Scope context_scope;

public:
    MyClass(); 
};

MyClass::MyClass():context(Context::New()),
    context_scope(Context::Scope(context))
{
}

如果Context :: Scope不是指针。

答案 3 :(得分:0)

要创建对象的实例,您只需要这样:Type name; new关键字创建指向对象的指针。通常,要初始化对象,我们使用括号:Type name(parameter);有时,当对象支持复制时,您可以使用返回对象并将其分配给该对象的函数:Type name = Some_function_that_returns_Type();您现在可以像任何其他对象一样使用name 。如果你说Type name = new Type;,你将收到编译器错误。 关键字new返回指针。Type * name = new Type;是正确的。 (请注意*,说它是Type类的指针,名为name。当我引用Type时,它是任意的对象,例如你的HandleScope。当我引用name时,它是你正在创建的新对象。总而言之: new是一个完全不同的关键字,指向指针。如果您没有使用指针,请不要使用它。使用基本格式Type name(parameter, another_param);