1

インスタンスを作成し、std:vector 型のプライベート メンバー変数にデータを格納する静的ファクトリ メソッド Foo::createOne を持つクラス Foo があります。Foo::createOne を呼び出すと、プログラムが次の例外をスローします: "EXC_BAD_ACCESS (メモリにアクセスできませんでした)"

コードは次のとおりです。

フー。

#include <vector>

class Foo {
public:
    Foo();
    Foo(const Foo& orig);
    virtual ~Foo();

    static Foo * createOne();

private:
    std::vector<int> v;

};

Foo.cpp

#include "Foo.h"

Foo::Foo() {
};

Foo::Foo(const Foo& orig) {
};

Foo::~Foo() {
};

Foo * Foo::createOne() {
    Foo *f;
    f->v.push_back(5);
    return f;
}

main.cpp

#include <iostream>
#include "Foo.h"

int main(int argc, char** argv) {

    std::cout << "Testing createOne." << std::endl;
    Foo *myFoo = Foo::createOne();
    std::cout << "It worked." << std::endl;

}

1つの問題を修正...

答えてくれてありがとう。初期化されていないポインターの問題を修正しました (下記)。現在、「ローカル変数 'f' のアドレスが返されました」というコンパイラ警告が表示されます。

Foo * Foo::createOne() {
    Foo f;
    f.v.push_back(5);
    return &f;
}
4

4 に答える 4

2
Foo *f;
f->v.push_back(5);

最初の行は生の初期化されていないポインターを作成しています。これは変数のインスタンスではないため、逆参照しようとするとUndefined Behaviorになります。

次のように、インスタンスに初期化する必要があります。

Foo *f = new Foo();
f->v.push_back(5);
// ...

delete f;

そうして初めて、コードが有効になります。


更新: コードをもう一度見直したところ、ポインターの使用はまったく不要であることがわかりました。値で返すことで、ほとんど同じことができます。

Foo Foo::createOne()
{
    Foo f;
    f.v.push_back(5);
    return f;
}

エラーaddress of local variable f returnedが発生した理由は、一時的な値へのポインターを返していたためです。関数が終了すると、ローカル変数fはメモリ不足になり、それへのポインターを設定することも未定義の動作になります。

于 2013-06-10T20:54:38.870 に答える
2

使用する前に Foo のインスタンスを作成する必要があります。ヒープでは、次を使用できます

Foo *f = new Foo();
于 2013-06-10T20:56:40.580 に答える
1

初期化されていないポインタを逆参照しています:

Foo *f;  // f not pointing to a Foo instance
f->v.push_back(5);

それは未定義の動作です。f有効なFooオブジェクトを指摘する必要があります。

于 2013-06-10T20:54:01.343 に答える
1

C++ では、ポインターを宣言するときに、次のようにコンストラクターを手動で呼び出す必要があります。

Foo * Foo::createOne() {
    Foo *f = new Foo; // <<=== Here
    f->v.push_back(5);
    return f;
}

これは、ポインターとしてではなく、オブジェクトとして定義されたオブジェクトとは異なります。

Foo Foo::createOne() {
    Foo f; // No initializer is necessary
    f.v.push_back(5);
    return f;
}

この場合、オブジェクトは値によって返されるため、そのコンテンツはプロセスでコピーされます。

オブジェクトを動的に作成する場合、次のように、メモリ リークを回避するために、ポインターが指すオブジェクトを削除する必要があります。

int main(int argc, char** argv) {

    std::cout << "Testing createOne." << std::endl;
    Foo *myFoo = Foo::createOne();
    std::cout << "It worked." << std::endl;
    delete myFoo;

}
于 2013-06-10T20:56:27.030 に答える