【问题标题】:Array size deduction数组大小扣除
【发布时间】:2020-04-20 21:40:17
【问题描述】:

按照 Scott Meyer 的“现代 C++”中的一个示例,我将利用模板来利用 std::array 大小推导。我在尝试编译我的 myUsage 函数用法时偶然发现。

#include <array>
#include <iostream>

template <typename T, std::size_t N>
constexpr std::size_t arraySize(T (&) [N]) noexcept
{
        return N;
}

void scottUsage()
{
        int b[5];
        std::array<short, arraySize(b)> c;
        std::cout << arraySize(b) << " = " << c.size() << "\n";
}

template <typename T, std::size_t N>
void myUsage(T & arr [N])
{
        for (auto i=0; i<arraySize(arr); i++)
                std::cout << arr[i] << "\t";
}

int main()
{
        scottUsage();

        int a[7];
        myUsage(a);
}

所以出现了两个问题:

  1. 附带问题(&amp;) 是干什么用的?删除会触发error: creating array of references,这似乎是被禁止的
  2. myUsage 签名有什么问题?

【问题讨论】:

  • 不应该是myUsage(T (&amp;arr) [N])吗?括号对于使其成为对数组的引用(而不是引用数组)很重要。
  • 当然,谢谢你们。请提供 cmets 作为答案(可能对 (&amp;varname) 不常见语法的解释很少,我很乐意标记为已解决
  • 另外,main() 中的a 是一个未初始化的int 数组。打印myUsage() 中的元素——一旦你用参数修正了拼写错误——因此会导致未定义的行为。
  • 真的是彼得?我以为我只是在阅读垃圾数据。无论如何,例如清酒
  • @PatrizioBertoni 最好让示例尽可能简单,以免意外引入与您的问题无关的错误。换句话说,示例应该最少。见minimal reproducible example

标签: c++ arrays c++11 templates stl


【解决方案1】:
  1. (&) 有什么用?

它使参数成为引用。如果它不是引用,那么它将是一个数组。但是函数参数不允许是数组,并且这样的声明被调整为指向数组元素的指针。由于该类型不携带数组大小信息,因此对大小推导没有用处。

删除会触发错误:创建引用数组,这似乎是被禁止的

void myUsage(T & arr [N])

确实,括号是强制性的。需要它们来表示引用适用于数组而不是数组的元素类型。 T&amp;[N] 是一个引用数组(这是不允许的),而T(&amp;)[N] 是一个数组引用。

  1. myUsage 签名有什么问题?

不允许引用数组。

【讨论】:

    【解决方案2】:

    myUsage()需要使用T (&amp;arr) [N]

    template <typename T, std::size_t N>
    void myUsage(T (&arr) [N])
    

    括号告诉编译器引用适用于数组本身,而不是数组的元素类型。

    另外,arraySize()myUsage() 都应该引用 const 数据:

    template <typename T, std::size_t N>
    constexpr std::size_t arraySize(const T (&) [N]) noexcept
    ...
    template <typename T, std::size_t N>
    void myUsage(const T (&arr) [N])
    

    顺便说一句,从 C++17 开始不再需要 arraySize(),而是使用 std::size()

    #include <array>
    #include <iostream>
    #include <iterator>
    
    void scottUsage()
    {
        int b[5];
        std::array<short, std::size(b)> c;
        std::cout << std::size(b) << " = " << c.size() << "\n";
    }
    
    template <typename T, std::size_t N>
    void myUsage(const T (&arr) [N])
    {
        for (auto i = 0; i < std::size(arr); ++i)
            std::cout << arr[i] << "\t";
        /* better:
        for (const T &value : arr)
            std::cout << value << "\t";
        */
    }
    
    int main()
    {
        scottUsage();
        int a[7];
        myUsage(a);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-11-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多