【问题标题】:Error in passing a map by reference to a function通过引用函数传递映射时出错
【发布时间】:2013-04-18 13:37:20
【问题描述】:

我想通过引用函数来传递地图。 代码如下:

void test(map<int, double *> &a);

int main(){
    map<int, double *> a;
    test(a);
    cout << a[1][1] << endl;
    return 0;
}

void test(map<int, double*> &a)
{
    double red[] = {1.1, 2, 3};
    a[1] = red;
}

问题是,a[1][1] 应该是 2。但是,当我执行程序时,它给出了一个大数字,例如 1.73e120 !!!

【问题讨论】:

  • 很奇怪。您的代码在此处输出 2:ideone.com/lyQAzd
  • @tacp 这是未定义的行为。它可以输出任何东西。
  • @juanchopanza 谢谢。了解 C++ 中所有未定义的行为可能会很好。
  • @tacp 好吧,越界访问数组是一种情况。

标签: c++ map containers pass-by-reference


【解决方案1】:
double red[] = {1.1, 2, 3};
a[1] = red;

危险!危险! red 是一个局部变量,在 test() 返回后被销毁。不要存储指向将在函数返回后使用的局部变量的指针。

您可以通过将其设为静态来解决此问题,因为静态变量永远存在。

static double red[] = {1.1, 2, 3};
a[1] = red;

或者你可以动态分配内存:

double *red = new double[]{1.1, 2, 3};
a[1] = red;

【讨论】:

    【解决方案2】:

    red 的定义创建的数组是 test 函数的本地数组。函数结束时将被销毁。您只是在map 中放置一个指向其第一个元素的指针,但一旦函数返回,该指针不再指向有效数组。数组消失了,指针悬空了。

    可以动态分配数组,但这很麻烦,并且可能导致内存泄漏和其他错误。

    相反,我建议使用标准容器类型,例如std::vector

    void test(map<int, std::vector<double>> &a)
    {
        a[1] = std::vector<double>{1.1, 2.0, 3.0};
    }
    

    【讨论】:

      【解决方案3】:

      您的地图将整数映射到指向双精度的指针。当您在函数中添加元素时,就像您在此处所做的那样,

      a[1] = red; // points to first element of local red[] array
      

      地图正在复制一个指向局部变量的指针。它指向的地址在test 函数之外毫无意义。指针不是数组,数组也不是指针。

      您可以改用向量图来解决此问题:

      std::map<int, std::vector<double>>
      

      然后

      void test(std::map<int, std::vector<double>> &a)
      {
        a[1] = std::vector<double>{1.1, 2., 3.};
      }
      

      【讨论】:

        【解决方案4】:
        double red[] = {1.1, 2, 3}; 
        

        具有自动存储期限。这意味着当函数返回时它不再有效。

        你应该这样做

        void test(map<int, double*> &a)
        {
            double *red = new double[3];
            // fill up red.
            a[1] = red;
        }
        

        【讨论】:

        • 它有自动存储期限,而不是静态的。
        • 动态分配可能不是最好的解决方案,因为现在您已经让用户负责记住正确删除它。存储像 std::arraystd::vector 这样的 RAII 类型会更好。
        • @MikeSeymour 是的,他可能可以使用向量。或者,如果地图的所有秒数的大小为 N,则为 N 大小的数组。然而,这只是他当前问题的解决方案。
        • 如果你有一个map&lt;int, double*&gt;,你怎么知道你应该打电话给delete还是delete[]?而你怎么知道元素没有在其他地方被删除?
        • 你怎么知道那些事?如果地图被复制会怎样?双重删除当然很重要。
        猜你喜欢
        • 2011-12-07
        • 1970-01-01
        • 2014-07-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-09-13
        • 2014-10-04
        相关资源
        最近更新 更多