简体   繁体   English

将向量中指向元素的指针设置为null,然后检查指针是否为null(C ++)

[英]Set pointer to element in vector to null, then check whether pointer is null (C++)

I would like to set pointers to some elements in my vector array to NULL (based on a criteria), and then check whether an element pointer is NULL. 我想将向量数组中某些元素的指针设置为NULL(基于条件),然后检查元素指针是否为NULL。 If the pointer pointing that element is NULL, I remove the element from my vector array. 如果指向该元素的指针为NULL,则从向量数组中删除该元素。

My compiler is giving me an error, saying that the address expression must be an lvalue or function designator and I do not understand why (line location commented in code). 我的编译器给我一个错误,说地址表达式必须是左值或函数指示符,而我不明白为什么(在代码中注释了行位置)。 Since I am taking the address of the value using & , am I not seeing if the pointer pointing to that element is NULL? 由于我使用&来获取值的地址,因此我是否看不到指向该元素的指针是否为NULL?

I included the preceding code as the error may lie there, 我加入了前面的代码,因为错误可能就在那里,

Relevant code: 相关代码:

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++;
    }
}

I am new to C++, and if you could suggest a more elegant way to do this, or a fix, it would be much appreciated. 我是C ++的新手,如果您可以提出一种更优雅的方式进行此操作或修复,将不胜感激。 I also assume that my method of setting the pointer to an element, noncollision[i].setxposint(NULL); 我还假设我将指针设置为元素的方法noncollision[i].setxposint(NULL); is correct? 是正确的? Can I return an integer using a function, and take the address? 我可以使用函数返回整数并获取地址吗?

Functions for getxpos and setxposint: getxpos和setxposint的函数:

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

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

You're using & to take a pointer to a temporary vale (the return from getxpos ) which isn't allowed; 您正在使用&指向不允许的临时值(从getxpos返回)的指针; since a temporary will be going away, the address won't be useful in any way so the language doesn't allow it. 由于临时文件将会消失,因此该地址将不会有任何用处,因此该语言不允许使用。 It certainly wouldn't ever be NULL even if you could get its address. 即使可以得到它的地址,它也永远不会为NULL。

noncollision[i].setxposint(NULL);

All that line is doing is setting xpos to zero. 该行所做的只是将xpos设置为零。 Generally the term NULL is used with pointers, and 0 is used with things like integers. 通常,术语NULL用于指针,而0用于整数之类的东西。 NULL is usually a macro for 0L anyway. 无论如何, NULL通常是0L的宏。

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

What this is doing, which is incorrect, is attempting to take the address of the return value from the member method getxpos() and compare it to NULL . 这是不正确的,它试图从成员方法getxpos()中获取返回值的地址并将其与NULL比较。 Whereas what you really want to do is simply see if the function returns zero. 而您真正想做的只是看函数是否返回零。 So simply change this line to: 因此,只需将此行更改为:

noncollision[i].getxpos() == 0

I'll explain why the compiler doesn't understand what you mean. 我将解释为什么编译器无法理解您的意思。

When you write 当你写

&(someFunction())

you are asking for the address of the thing that the function returns . 您要查询函数返回的内容地址 But functions return values. 但是函数返回值。 A value doesn't have an address. 值没有地址。 Variables have addresses. 变量有地址。

When something is a word of memory (which will contain a value), it can be used as an lvalue (left-value), because you can put things into that word of memory: 当某物是一个内存字(将包含一个值)时,它可以用作左值 (左值),因为您可以将内容放入该内存字中:

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

When something is just a value, it can only ever be used as an rvalue . 当某物只是一个值时,它只能用作rvalue The following would not compile, for the same reason that your code would not: 出于与您的代码不相同的原因,以下内容将无法编译:

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.

(Caveat: you can use values to refer to words in memory: this usage is called a pointer, eg (注意:您可以使用值来引用内存中的单词:这种用法称为指针,例如

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

meaning "put the value of b into the memory which has the address 42 . This compiles fine (but crashes if you're not allowed to write to the memory at 42.) 意思是“将b的值放入具有地址42的内存 。这可以正常编译(但是如果不允许您在42处写入内存,则会崩溃。)

It seems that you are trying to check pairs of points for collisions. 看来您正在尝试检查点对是否存在碰撞。 You then record for each point whether it has any collision. 然后,为每个点记录是否有碰撞。 This is best handled by a simple list of flags: 最好通过简单的标志列表来处理:

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

Afterwards: 然后:

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

At the end, iterate over the list of flags and get the points that have no collisions: 最后,遍历标志列表并获得没有冲突的点:

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

In addition: using a vector to hold a pair (i,j) of points is confusing. 另外:使用vector保存一对(i,j)点是令人困惑的。 Standard library has the std::pair type for purposes such as this. 标准库出于这种目的具有std::pair类型。

Also: you don't need explicit dynamic allocation ( new ); 另外:您不需要显式的动态分配( new ); let Standard Library manage memory for you in a safe, non-confusing way. 让标准库以安全,不混乱的方式为您管理内存。 Instead of 代替

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

Use 采用

vector<vector<particle>> collisionlist;

(or vector<pair<particle, particle>> , as described above). (或如上所述的vector<pair<particle, particle>> )。

It looks to me you're trying to keep track of 'visited' items, not sure exactly in which way. 在我看来,您正在尝试跟踪“已访问”的项目,不确定到底是哪种方式。

Instead of "modifying" the items, you could use an "external" mark. 您可以使用“外部”标记来代替“修改”项目。 A set looks to be fine here. 一套看起来很好。 You could use a set of iterator s into the particle list, or in this case a set of indices ( i , j ) which will likely be more stable. 您可以在粒子列表中使用一组iterator s,或者在这种情况下使用一组可能更稳定的indicesij )。

Here's a start: 这是一个开始:

#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
    }
}

NOTE Be very very wary of floating point comparison like 注意请非常警惕浮点比较,例如

 if (d==0.0) // uhoh

because it will likely not do what you expect 因为它可能不会达到您的期望

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM