【问题标题】:Passing an array of pointers and return an array of values pointed by those pointers传递一个指针数组并返回一个由这些指针指向的值数组
【发布时间】:2015-01-16 08:07:35
【问题描述】:

我想编写一个函数,将n 指针数组传递给float,并返回一个包含n float 值的新创建数组。代码如下:

float* duplicate(float* p[], int n){
    float* const b = new float[n];
    for (int i = 0; i < n; i++)
        b[i] = *p[i];
    return b;
}

我的问题是,我们为什么要将b 声明为const?如果我删除const,结果会受到什么影响?非常感谢!

【问题讨论】:

  • 通过使用clockwise/spiral rule,变量b是一个指向float的常量指针,也就是说这个指针是常量,你不能改变它。
  • 代码无效,我想你的意思是return b;。在这种情况下,将b 设为const 指针没有任何区别,无论您是否这样做,代码都很糟糕。请改用std::vector&lt;float&gt;
  • 对不起,这是一个错字。是返回 b; .谢谢指出!
  • 澄清一下,p 中的每个指针都指向一个浮点数? (不是数组的第一个浮点数)?
  • @Praetorian 为什么他们应该使用向量来代替?

标签: c++ pointers constants


【解决方案1】:

b 声明为

float* b = ...;

在这里也同样有效。 const 表示存储在b 中的指针(指向floats 数组的开头)不能更改。

由于代码无论如何都不会尝试更改它(如果尝试将无法编译),删除 const 不会有任何区别。

const 是一种安全机制。程序员要求编译器“告诉我如果我试图用这个变量做一些愚蠢的事情”。作为一般规则,默认情况下设置const 是个好主意,除非您确实知道需要更改它们。这意味着您不会意外地分配给您无意分配的东西,从而使您可能难以追踪错误。

(也有一种说法是编译器对const有更多的优化机会。在某些情况下可能是这样,但在这里有点无关紧要。在这种情况下,安全是主要关注点。)

但在这种情况下,所有手动内存管理和使用指针都是自找麻烦,您最好使用为您完成所有这些工作的库组件,例如 std::vector

编辑:为了完整起见,这里有一个使用std::vector的版本:

std::vector<float> duplicate(float* f[], std::size_t n)
{
    std::vector<float> copyOfF;
    copyOfF.reserve(n); // save enough space; not essential
    std::transform(f, // front of f
                   f+n, // back of f
                   std::back_inserter(copyOfF), // push them into the vector
                   [](float* f){return *f;} ); // deref the pointers
    return copyOfF; // will steal the internal array
}

【讨论】:

    【解决方案2】:

    float* const b 中的const 表示指针无法更改。例如,这将无法编译:

    float* const b;
    

    在你的情况下,如果你删除 const,什么都不会改变。

    【讨论】:

      【解决方案3】:

      当你创建一个变量const,你不能在初始化之后改变它的值。

      所以,当你写的时候:

      float* const b = new float[n];
      

      您是在告诉编译器b 的内容不会在下一行代码中更改。而且,如果由于某些原因,您更改了它(例如,通过重新分配 b 变量),您将收到编译器错误。

      您可以将const 视为“只读”,即b 的值(即new[] 调用返回的地址)不能 em> 在以下代码行中进行更改。

      请注意,您可以更改由new[]分配的数组的内容!事实上,正如您编写的代码,const 仅适用于 b 的值(即 new[] 返回的内存地址),不适用于 指向的数组的内容b.

      请注意,如果您编写这样的代码:

      const float* b = ...
      

      那么,这完全不同。实际上,在这种情况下,您可以更改 b 的值,例如您可以重新分配 b 以指向其他内容,无法更改 b 所指向的数组的内容

      而且你还可以将两个consts的效果结合起来,例如

      const float * const b = ...
      

      在这种情况下,您不能更改b 的值(即不能重新分配b)或b 指向的数组的内容。

      当然,在您的情况下,由于您想将一些内容写入使用new[] 分配的数组中,因此仅使用const 来表示b(指针)的值是有意义的,而不是指向的数组。换句话说,b 指向的数组应该是可读写的(即非const),而不是只读的(即const)。


      注意:在现代 C++ 中,通常最好使用一些 容器类,例如 std::vector,而不是使用原始 new[] 分配内存。
      (使用std::vector 的优点之一是vector 中存储的内存和资源通过vector 的析构函数自动释放。)

      因此,除非这是一个学习实验代码,或者您有充分的理由使用 new[],否则请考虑在现代 C++ 中对动态分配的数组使用 std::vector

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-08-18
        • 1970-01-01
        • 1970-01-01
        • 2017-08-23
        • 1970-01-01
        • 2020-09-16
        • 2011-01-12
        相关资源
        最近更新 更多