1

私はJavaを知っていますが、C++についてはあまり知識がありません。https://developers.google.com/v8/get_startedで、コードのメイン関数の最初の3つのステートメントのクラスを作成しようとしています。

まず、C++でオブジェクトを作成する方法について質問します。以下のコードを参照してください。

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

C ++では、クラスの変数を宣言すると、その時点で作成されたクラスのインスタンスになると思います。Javaのように新しいキーワードを使用する必要はありません。したがって、最初のステートメントは、handle_scopeに格納されるHandleScopeのインスタンスを作成します。今、私は2番目のステートメントがどのように機能するかを理解していません。私の知る限り、=の前の部分は、変数コンテキストで参照できる新しいPersistentオブジェクトを作成します。次に、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 {public:Test(){cout << "Test" << endl; }};

主な機能で、私はテストテストを書きました。新しいキーワードを使用せずにオブジェクトが作成されることを意味する「テスト」を出力します。

4

4 に答える 4

11

そうです、C ++では、オブジェクトは定義されるとすぐに作成されます。newキーワードを使用する必要はありません。

ただし、Javaとは異なり、オブジェクトはさまざまな種類の期間で作成できます。を使用すると、動的なnew保存期間でヒープ上にオブジェクトが作成されます。変数は、明示的に指定するまで存続します。(そして、作成されたオブジェクトへのポインタを返すので、それを追跡できます)deletenew

1行目と3行目のようにオブジェクトを定義するだけの場合、オブジェクトは自動保存期間で作成されます。つまり、オブジェクトはスコープ外になるまで存在します。

これは、関数内にオブジェクトを作成でき、関数を離れる方法に関係なく、関数を離れるとすぐにオブジェクトが破棄されることが保証されることを意味します。戻るか例外をスローするかにかかわらず、自動保存期間(を使用せずに作成された)を持つすべてのオブジェクトは、適切にクリーンアップされることが保証されます。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適切に破棄されるので、Javaのようにtry/をいじる必要はありません。finallyこのクラスは、ユーザーによる追加の作業を必要とせずに、それ自体で例外安全です。

Javaで同様のスニペットを作成してみてください。これにより、例外がスローされた場合でも、ファイルがすぐに閉じられることが保証されます。doStuffそれははるかに長くなり、ユーザーの側でより多くの注意を必要とします。

于 2012-07-29T17:50:38.120 に答える
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を構築し、コンテキストをコンストラクターに渡します。私の例のように、コンストラクタ初期化構文を使用すると、クラスで同等の動作が得られます。

于 2012-07-29T17:50:13.013 に答える
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がポインターでない場合。

于 2012-07-29T17:53:14.483 に答える
0

オブジェクトのインスタンスを作成するには、これだけが必要ですType name; newキーワードは、オブジェクトへのポインターを作成します。通常、オブジェクトを初期化するには、括弧を使用します。Type name(parameter);オブジェクトがコピーをサポートしている場合、オブジェクトを返す関数を使用して、そのオブジェクトに割り当てることができます。他のオブジェクトと同じようにType name = Some_function_that_returns_Type();使用できるようになりました。nameと言うとType name = new Type;、コンパイラエラーが発生します。キーワードnewはポインタを返します。と言うのは正しいでしょうType * name = new Type;。(、という名前のクラスへのポインタ*であることに注意してください。私が参照するときは、HandleScopeなどの任意のオブジェクトです。私が参照するときはTypenameTypename、それはあなたが作成している新しいオブジェクトです。すべてはこれです:newポインタを参照する完全に異なるキーワードです。ポインタを使用していない場合は、使用しないでください。基本形式を使用しますType name(parameter, another_param);

于 2012-07-29T18:14:52.030 に答える