1

ベクトル配列内のいくつかの要素へのポインターを (基準に基づいて) NULL に設定し、要素ポインターが NULL かどうかを確認したいと考えています。その要素を指すポインターが NULL の場合、ベクター配列からその要素を削除します。

アドレス式は左辺値または関数指定子である必要があり、その理由がわかりません (行の場所はコードでコメントされています)。を使用して値のアドレスを取得している&ため、その要素を指すポインターが NULL であるかどうかがわかりませんか?

エラーがそこにある可能性があるため、前のコードを含めました。

関連コード:

vector<particle> pl = c.particlelist;
vector<particle> noncollision = c.particlelist;
vector<vector<particle>> collisionlist = new vector<vector<particle>>();
for (int i = 0; i < c.numparticles-1; i++){
    particle first = pl[i];
    for (int j = i+1; j < c.numparticles; j++)
    {
        particle second  = pl[j];
        double d = distance(first, second);
        if (d==0)
        {
            vector<particle> temp = {pl[i], pl[j]};
    collisionlist.push_back(temp);
            noncollision[i].setxposint(NULL); 
            noncollision[j].setxposint(NULL);
        }
        else
        {
        }
    }
}
int j = 0;
for (int i = 0; i < noncollision.size(); i++)
{
    if (&(noncollision[i].getxpos()) == NULL) ////// ERROR HERE
    {
        noncollision.erase(noncollision.begin()+i);
    }
    else
    {
        j++;
    }
}

私は C++ を初めて使用します。これを行うためのよりエレガントな方法または修正方法を提案できれば、非常にありがたいです。また、要素へのポインターを設定する方法noncollision[i].setxposint(NULL);は正しいと思いますか? 関数を使用して整数を返し、アドレスを取得できますか?

getxpos および setxposint の関数:

int particle::getxpos(){
return xpos;
}

void particle::setxposint(int b){
xpos = b;
}
4

5 に答える 5

3

許可されていない&一時的な値 ( からの戻り値) へのポインターを取得するために使用しています。getxpos一時的なものはなくなるため、アドレスはまったく役に立たないため、言語では許可されません。アドレスを取得できたとしても、NULL になることはありません。

于 2013-08-04T20:52:52.437 に答える
2

コンパイラがあなたの意味を理解できない理由を説明します。

あなたが書くとき

&(someFunction())

関数が返すもののアドレスを求めています。しかし、関数は値を返します。値にはアドレスがありません。変数にはアドレスがあります。

何かがメモリの単語 (値を含む) である場合、そのメモリの単語に物を入れることができるため、左辺値(左辺値) として使用できます。

int b = 1; //make room for an `int` on the stack, then put a `1` there.

何かが単なる値の場合、それはrvalueとしてのみ使用できます。あなたのコードがコンパイルしないのと同じ理由で、以下はコンパイルされません:

int b; //make room for an `int` on the stack.
42 = b; //ERROR, this makes no sense.
if (42 == NULL) { std::cout << "this is never true" << std::endl; }
&42; //ERROR, 42 isn't a piece of memory, it's a value.

(注意: 値を使用してメモリ内の単語を参照できます: この使用法はポインターと呼ばれます。

int b = 1;
*((int *)(42)) = b;

これは、「 の値をアドレスを持つbメモリに入れることを意味します。これは問題なくコンパイルされます (ただし、42 のメモリへの書き込みが許可されていない場合はクラッシュします。)42

于 2013-08-04T21:17:20.017 に答える
2

noncollision[i].setxposint(NULL);

その行が行っているのはxpos、ゼロに設定することだけです。一般に、この用語NULLはポインタとともに0使用され、整数などとともに使用されます。NULLとにかく、通常はマクロ0Lです。

&(noncollision[i].getxpos()) == NULL

これが行っていることは正しくありませんが、メンバー メソッドから戻り値のアドレスを取得し、getxpos()それを と比較しようとしていNULLます。本当にやりたいことは、関数がゼロを返すかどうかを確認することです。したがって、この行を次のように変更するだけです。

noncollision[i].getxpos() == 0

于 2013-08-04T20:37:25.153 に答える
1

「訪問した」アイテムを追跡しようとしているように見えますが、正確な方法はわかりません。

アイテムを「変更」する代わりに、「外部」マークを使用できます。ここはセットで良さそうです。iterators のセットをパーティクル リストに使用できます。この場合、 indices( i, j) のセットを使用すると、より安定する可能性があります。

ここから始めましょう:

#include <vector>
#include <set>

struct particle { };

double distance(particle const&, particle const&) { return 1.0; }

struct context
{
    std::size_t numparticles;
    std::vector<particle> particlelist;

    context() : numparticles(100), particlelist(numparticles) {}
};

static context c;

int main()
{
    using std::vector;
    using std::size_t;

    vector<particle> pl = c.particlelist;
    vector<vector<particle>> collisionlist;

    std::set<size_t> collision;

    for(size_t i = 0; i < c.numparticles-1; i++)
    {
        particle first = pl[i];
        for(size_t j = i+1; j < c.numparticles; j++)
        {
            particle second  = pl[j];
            double d = distance(first, second);
            if(d < 0.0001)
            {
                collisionlist.push_back({pl[i], pl[j]});
                collision.insert(i);
                collision.insert(j);
            }
            else
            {
            }
        }
    }

    for(size_t i = 0; i < pl.size(); i++)
    {
        if(collision.end() != collision.find(i))
        {
            // do something
        }
    }

    // alternatively
    for (int index : collision)
    {
        particle& p = pl[index];
        // do something
    }
}

次のような浮動小数点比較には十分注意してください。

 if (d==0.0) // uhoh

期待どおりに動作しない可能性が高いため

于 2013-08-04T20:55:16.277 に答える
1

ポイントのペアの衝突をチェックしようとしているようです。次に、各ポイントに衝突があるかどうかを記録します。これは、フラグの単純なリストで処理するのが最適です。

std::vector<bool> has_collision(c.numparticles, false); // init: no collisions found

その後:

    if (d==0)
    {
        has_collision[i] = true;
        has_collision[j] = true;
    }

最後に、フラグのリストを繰り返し処理し、衝突のないポイントを取得します。

for (size_t i = 0; i < c.numparticles; ++i)
{
    if (!has_collision[i])
    {
        // whatever
        // possibly push_back pl[i] into some list
    }
}

さらに、ポイントvectorのペアを保持するために a を使用するの(i,j)は混乱を招きます。標準ライブラリには、std::pairこのような目的のために型があります。

newまた、明示的な動的割り当て ( )は必要ありません。標準ライブラリに、安全で混乱のない方法でメモリを管理させます。それ以外の

vector<vector<particle>> collisionlist = *new vector<vector<particle>>();

使用する

vector<vector<particle>> collisionlist;

(またはvector<pair<particle, particle>>、上記のように)。

于 2013-08-04T20:50:07.443 に答える