【问题标题】:C++ pointer arithmetic "lvalue required as left operand of assignment" errorC++ 指针算术“需要左值作为赋值的左操作数”错误
【发布时间】:2019-12-11 09:28:16
【问题描述】:

我正在尝试创建一个指针数组。初始化每个指针时,我不能使用 (ptr + 1) 来分配一些东西。

示例代码:

int* demo = (int*) malloc(5*sizeof(int));
int a = 1;
int b = 2;
int* pa = &a;
int* pb = &b;
demo = pa;
demo+=1;
demo = pb;

会起作用,而

int* demo = (int*) malloc(5*sizeof(int));
int a = 1;
int b = 2;
int* pa = &a;
int* pb = &b;
demo = pa;
(demo + 1) = pb;

不会。它在最后一行显示错误:“需要左值作为赋值的左操作数”。

有什么方法可以使用(因为没有更好的术语)“临时递增指针”,还是我只需要存储原始指针并通过递增我的指针来遍历我的数组?

【问题讨论】:

  • 你的代码没有意义。 demo = malloc(...); demo = ... 是内存泄漏。你想在这里做什么?
  • 您希望(demo + 1) = pb 如何工作?你认为它应该怎么做?
  • int x = 0; x + 1 = 3;的情况相同。指针没有什么特别之处。
  • 是的,你想做什么?与流行的看法相反,过度使用指针并不会让你成为更好的程序员。
  • 您确定您使用的是 c++ 而不是 C?对于这样的事情,如果没有 malloc,你会好得多。

标签: c++ pointers pointer-arithmetic


【解决方案1】:

我正在尝试创建一个指针数组。

好吧,int *demo 创建了一个指针,而不是它们的数组。

如果你想要一个指针数组,你需要这样做:

int *demo[5];
int a = 1;
int b = 2;
demo[0] = &a;
demo[1] = &b;

由于x[y]对于指针等价于*(x + y),所以最后两行也可以写成

*(demo + 0) = &a;
*(demo + 1) = &b;

另一方面,如果你只是想动态分配一个整数数组,你可以这样做:

int *demo = new int[5];
demo[0] = 1;
demo[1] = 2;
// Or (as above):
// *(demo + 0) = 1;
// *(demo + 1) = 2;
...
delete[] demo;

但我建议使用标准容器(例如std::vector)而不是手动调用new[]

【讨论】:

    【解决方案2】:

    所以你首先分配内存并将其分配给demo。你接下来将demo 瞄准&a,然后泄漏内存。原始值(由 malloc 返回的值)被&a 覆盖,这可能与返回的指针相去甚远。堆与堆栈。

    对于每个malloc,必须有一个free。对于每个new,必须有一个delete。您的代码没有free,因此不干净。它可能只有被神圣的人神圣化......呃无论如何。只是不要忘记free你的记忆。

    “L 值”是指“在赋值的 LEFT(因此是 L)上有效的值”。 demo + 1 创建一个临时值,它会立即消失。

    指针和数组在 C/C++ 中完全可以互换。看起来您想要做的是demo[0] = &ademo[1] = &b... 将值写入在演示中分配和存储的那个区域。您并不是要重写 demo 本身,以及 demo 本身旁边的任何内容(恰好是 a)具有 64 位值(这也将超越 b)。

    您还将 int* 值(一个 64 位指针)写入整数数组(在大多数但不是所有平台上都是 32 位值)。

    鉴于这是 C++,您可能会更高兴:

        std::vector<int*> demo;
        int a = 1;
        int b = 2;
        demo.push_back(&a);
        demo.push_back(&b);
    

    你让 std::vector 做所有的分配和释放。没有麻烦,没有大惊小怪,没有资源泄漏。

    对于向量,您必须牢记一些事情。 “空间”和“大小”不一样。

        std::vector<int*> badIdea();
        badIdea.reserve(5); // Preallocating is good, right?  room for 5 (or maybe a bit more).
        assert(badIdea.size() == 0);
        badIdea[0] = nullptr; // bad news. Writing into the memory but not actually changing the vector's idea of how big it is.
        assert(badIdea.size() == 0);
        badIdea.push_back(&someInt);
        assert(badIdea.size() == 1); // so &someInt was written over that nullptr
    

    如果您使用非平凡析构函数的向量,这将成为一个更糟糕的主意。

        std::vector<someClass> reallyBadIdea;
        reallyBadIdea[0].someFunction(); // the object at [0] hasn't been constructed yet
        reallyBadIdea.push_back(stuff);
    

    万一 someFunction() 没有在你的脸上爆炸,如果 someFunction() 分配了一些要在析构函数中释放的东西会发生什么。因为vector 认为reallyBadIdea[0] 中没有对象,所以它只是在stuff 上运行someClass 的复制构造函数。它从不运行析构函数来清理那里不存在的对象。

    所以标准容器很棒,但你真的必须先了解一些关于它们的事情,否则你只是乞求自己在脚下开枪。

    【讨论】:

    • 这是 OP 能得到的最佳答案。
    • assert badIdea.size() == 0; 甚至无法编译。这是语法错误。
    • 围绕“空间”/“大小”和预分配的整个解释是错误的。 std::vector&lt;someClass&gt; reallyBadIdea(1); 创建一个大小为 1 的向量,并构造一个元素。第一个示例使用std::vector&lt;int*&gt; demo(5); 和两个push_backs 创建一个七元素向量。
    • 这就是我在 C++ 和 Java 之间来回走动的结果。这能通过吗?
    • 当你工作的最后两家公司都有自己的容器类,然后你又开始使用 std::containers 时,就会发生这种情况。哦。
    猜你喜欢
    • 2017-01-10
    • 2023-04-02
    • 1970-01-01
    • 2011-12-20
    • 2011-03-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多