C++ 指针取消引用赋值

Posted

技术标签:

【中文标题】C++ 指针取消引用赋值【英文标题】:C++ Pointer Dereferenced Assignment 【发布时间】:2014-06-12 01:32:08 【问题描述】:

在开始使用诸如 std::copy 或 memcpy 之类的抽象之前,我正在尝试通过首先了解底层细节来学习 C++。目前,我一直在试图弄清楚为什么这段代码从未分配给“sortedArray”变量,当使用调试器查看时,我正确地取消了“data”中的值,但它从未分配给“sortedArray”。对于第一个值,我看到诸如“-842150451”之类的值而不是“14”。你能帮我弄清楚我做错了什么吗?任何其他我看不到的问题或建议将不胜感激!

void swap(int* bigger, int* smaller)
    *bigger += *smaller;
    *smaller = *bigger - *smaller;
    *bigger = *bigger - *smaller;


int* bubbleSort(int *data, int size)
    bool swapped = true;
    int *sortedArray = (int*)malloc(size*sizeof(int));
    for (int i = 0; i < size;i++)
        *(sortedArray++) = *(data++);
    

    while (swapped)
        swapped = false;
        for (int i = 1; i <= size - 1; i++)
            if (sortedArray[i - 1] > sortedArray[i])
                swap(&sortedArray[i - 1], &sortedArray[i]);
                swapped = true;
            
        
        size--;
    
    return sortedArray;

【问题讨论】:

这是您的问题:*(sortedArray++) = *(data++); 这是另一个:swap(&amp;sortedArray[i - 1], &amp;sortedArray[i]); 还有一个:你没有使用std::vector 你不是在学习C++,这是C代码。 I am trying to learn C++ by firstly going through the low level details 在你这样做的同时,B 人正在学习更高的抽象,从而生成高效、无错误的程序。 【参考方案1】:

*(sortedArray++) = *(data++); 修改指针,使其不再指向已分配内存的开始。因此,稍后sortedArray[i] 是内存中超出数组的任何内容,访问它是未定义的行为。

如果你必须使用指针,一个快速的解决办法是使用一个临时的,比如:

int *sortedArray = (int*)malloc(size*sizeof(int));
int* s = sortedArray;
for (int i = 0; i < size;i++)
    *s++ = *data++;

另一种方法是:

int *sortedArray = (int*)malloc(size*sizeof(int));
for (int i = 0; i < size;i++)
    sortedArray[i] = data[i];

但是,最好的方法是使用标准容器和算法,例如 vectorsort

这是demo 的第一个正在行动的修复程序。

【讨论】:

谢谢你的解释,现在看起来很明显......我打算很快看看容器,谢谢:) error: ‘malloc’ was not declared in this scope 所以只需要添加一个字符串#include &lt;cstdlib&gt; @RuslanGerasimov 啊,你的意思是在演示中。它可以在没有它的情况下在 ideone 和 Visual Studio 上编译,但为了最安全,我还是添加了它。我使用malloc,所以我很少忘记这一点。感谢您指出。【参考方案2】:

改变

*(sortedArray++) = *(data++);

sortedArray[i] = data[i];

您需要保留指向您分配的内存块的指针,以便以后使用它(并释放它)。

注意,使用*(x+y) 语法代替x[y] 并没有什么好处,它们是等价的,但后者更容易阅读。

在 C++ 中,您不应使用 malloc。而是使用new int[size]。对于int,除了减少打错的风险之外没有其他区别,但是对于非平凡类型malloc 将无法正确构造它们。

【讨论】:

感谢您对new []的建议,我以后会使用它。【参考方案3】:

那根本不是 C++。您可以编写带有 begin 迭代器和 end 迭代器的通用代码,以便它与支持此类语义的任何类型的容器一起使用。

template<typename IT>
void bubble_sort(IT begin, IT end) 
    while (true) 
        bool swapped = false;
        for (IT i = begin; i != end-1; i = i+1) 
            if (*i > *(i+1)) 
                std::iter_swap(i, i+1);
                swapped = true;
            
        
        if (swapped == false) return;
    

Live demo

std::iter_swap 类似于std::swap,但适用于迭代器。您可以将迭代器视为一对指向容器开头和(过去)结尾的指针。

【讨论】:

你能不能更神秘一点,这对OP没有帮助。 报错,单行修复即可。 @self。这并没有改变 1) 这不是 C++ 的事实; 2) 该代码不应永久存在; 3)他可以从上面的代码中学到更多,而不是对他的“简单”修复。 OP 用 c、c++ 标记了问题并发布了一些代码。您的代码不仅与他的风格不同,而且完全不同,甚至引入了对于问题完全没有必要的模板(?)。您还发布了一个完整的代码示例,OP 现在可以愉快地复制/粘贴。他会从中学到什么? @self。用 C C++ 标记问题完全没有意义。我们可以假设他的意思是 C++。它引入了模板,因为它们是一个不错的选择,并邀请用户了解它们。如果他只是要复制和粘贴代码,那么我(或者你)可以为他做的事情并不多。【参考方案4】:

你的第一个指针 sortedArray 指向一些分配的内存。

然后在第一个 for 循环中增加指针。不是它不再指向那个记忆。

只需对内存副本使用临时指针。

int* t = sortedArray ;

现在在复制数据的 for 循环中使用 t

您可以计算在 for 循环中调用 sortedArray++ 的次数,而不是临时变量。

如果您看一下:for (int i = 0; i &lt; size;i++),您会发现循环恰好采用了 size 的迭代次数。

只需在循环后从指针中减去大小,然后指向分配的内存。

sortedArray -= size ;

【讨论】:

也感谢您的回答,t make use of a auxiliary variable, I didnt 没有注意到这个细节。 你真的推荐指针算法吗?这是 OP(或任何新程序员)应该学习的答案吗?我怀疑。 @Jefffrey 是的,因为他在他的代码中使用了指针算法,这就是问题所在。这是向他提供有关该主题的更多信息的最佳时机。 @self。难怪。指针算法经常引入错误和运行时错误。它也是不可读的,并且有更好的方法来解决这个问题。在 C++ 社区中众所周知,使用指针是您最不想做的事情。简单的答案并不总是正确的。 @self。我到底在哪里误解了任何东西?

以上是关于C++ 指针取消引用赋值的主要内容,如果未能解决你的问题,请参考以下文章

如何在 C++ 中取消引用指针对象?

C++ 构建警告:取消引用类型双关指针将破坏严格别名规则

C++ 中指针取消引用的随机行为

不评估应用了 sizeof 的表达式是不是使得在 C++ 中取消引用 sizeof 内的空指针或无效指针是合法的?

Go 指针、引用、取消引用的规则:

取消引用指向访问元素的向量指针