当数组是类的数据成员时,如何使用指针交换数组

How to swap array using pointer when array is a data member of a class

本文关键字:数组 何使用 交换 指针 数据成员      更新时间:2023-10-16

我试图通过交换指向两个数组的指针来交换数组中的内容。

我的方法与 Daniel 在这个问题中回答的方法相同:在 C++ 中使用指针交换数组。但不同的是,我的数组将是类中的成员。我的代码可以成功编译,但输出结果很奇怪。

这是我的头文件:

#include <stdio.h>
#include <iostream>
class Map
{
public:
    Map(int times); // Create an empty map (i.e., one with no key/value pairs)
    int size();     // Return the number of key/value pairs in the map.
    void dump();
    void swap(Map &other);
    int *retrieve();
    void setptr(int *newptr);
private:
    int *ptr;
    int array_1[5];
};

这是我的实现:

#include "Map.h"
#include <iostream>
using namespace std; 
Map::Map(int times) {
    for (int i = 0; i < 5; i++) {
        array_1[i]=i*times;
    }
    ptr=array_1;
}
void Map::dump() {
    ptr=array_1;
    for (int i = 0; i < 5; i++) {
        cout << *ptr << endl;
        ptr++;
    }
    for (int i = 0; i < 5; i++) {
        ptr--;
    }  
}
void Map::swap(Map &other) {
    int *temp;
    temp = this->ptr;
    this->ptr = other.retrieve();
    other.setptr(temp);
}
int *Map::retrieve() {
    return ptr;
}
void Map::setptr(int *newptr) {
    ptr=newptr;
}

谁能告诉我出了什么问题以及如何巧妙地实施它?

以下代码运行良好:

#include <stdio.h>
#include <iostream>
#include <conio.h>
using namespace std; 
class Map
{
public:
    Map(int times);         // Create an empty map (i.e., one with no key/value pairs)
    int size();    // Return the number of key/value pairs in the map.
    void dump();
    void swap(int &other);
    int *retrieve();
    void setptr(int *newptr);
private:
    int *ptr;
    int array_1[5];
};

Map::Map(int times){
    for (int i=0;i<5;i++){
        array_1[i]=i*times;
    }
    ptr=array_1;
}
void Map::dump(){
    for (int i=0;i<5;i++)
    {
        cout<<ptr[i]<<endl;        
    }
}
void Map::swap(int &other){
    int *temp;
    temp=this->ptr;
    this->ptr=&other;
    other = *temp;
}
int *Map::retrieve(){
    return ptr;
}
void Map::setptr(int *newptr){
    ptr=newptr;
}
int main()
{
    Map m(2);
    Map n(3);
    m.dump();
    m.swap(*n.retrieve());
    m.dump();
    getchar();
}

1)增加了一个主功能
2) 更改了交换功能但是克里斯托弗指出的问题仍然存在,即指针将指向另一个对象中的数组。

编辑:您可能需要这样的东西:

void Map::swap(Map &other){
    Map *temp;
    temp=this;
    *this = other;
    other = *temp;
}
Map *Map::retrieve(){
    return this;
}

注意:它可能不优雅。

设计的问题在于指针引用同一对象中的数组。

假设您必须对象 a 和 b。 如果交换它们的指针,a.ptr 将指向包含数据的b.array_1。 倒数 b.ptr 将指向 a.array1。

不幸的是,如果其中一个对象 - 比如b - 被销毁(因为它是一个超出范围的本地对象,或者出于任何原因),其余对象的指针将指向一个不再存在的数组。 这是 UB。

为了解决您的问题,您需要在构造函数中动态分配一个数组。完全摆脱array_1:

Map::Map(int times){
    ptr=new int[5];  // or better define a constant to avoid hard coded sizes        
    for (int i=0;i<5;i++){
        ptr[i]=i*times;
    }
}

请注意,如果使用指针,则需要确保指针上的不变量。 这意味着您还应该定义复制构造函数和赋值运算符(以避免盲目复制 ptr),以及析构函数(删除动态分配的数组)。

PS:我想你正在学习C++,还不熟悉向量。这些将避免这里的所有麻烦

编辑:如果您在销毁任何对象之前遇到问题,那是因为dump()的实现不佳:您将指针递增到那里,以便它不再指向数组的开头。

void Map::dump(){
    for (int i=0;i<5;i++){
        cout<<ptr[i]<<endl;  // don't change ptr value !! 
    }
}

避免此类问题的一个简单技巧是系统地将不应该更改对象状态的成员函数声明为 const:

class Map {
   ...
   void dump() const;
   ...
}

然后,如果您尝试意外更改成员,编译器将发出错误。