【问题标题】:array of integers vs. pointer to integer in c++整数数组与 C++ 中指向整数的指针
【发布时间】:2009-07-15 18:41:04
【问题描述】:

如果我有int x[10]int *y,我如何区分两者?

我有两个想法:

  1. sizeof() 不同。

  2. &x 有不同的类型 --- int (*p)[10] = &x 有效,但 int **q = &x 无效。

还有其他人吗?

在某些模板库代码中,我需要确定一个指针是“真实”指针还是从数组退化而来。在我编写库之前,我无法查看源代码,因为库用户不存在。 ...我可以通过重写代码来解决这个问题,所以现在这只是一个理论练习。

【问题讨论】:

  • 您所说的“区分”到底是什么意思?为什么“检查类型声明”不是一个完整的解决方案?您是否需要对模板部分特化或类似的行为有一些不同的行为?
  • 会有sizeof相等的情况。无论如何,查看差异的简单方法是查看源代码。您要解决的真正问题是什么?

标签: c++ arrays pointers


【解决方案1】:

没有通用的方法——你要么已经知道类型,因为你刚刚声明了对象,要么类型将衰减为指针并丢失。请通过区分它们来解释您要解决的问题。

【讨论】:

  • 同上 :-)
  • 我怀疑他要么正在编写一些区分数组或指针的模板代码,要么正在尝试编写指针失败的数组计数函数/宏。
【解决方案2】:

sizeof 的想法不是很好,因为如果数组恰好只有一个元素,而元素类型恰好和指针大小一样,那么它的大小就会和 a 的大小一样指针。

类型匹配方法看起来更有前途,并且可能用于选择模板专业化(如果您愿意的话)。

【讨论】:

    【解决方案3】:

    假设您没有尝试对在函数范围内声明的类型执行此操作:

    struct yes { char pad; };
    struct no { yes pad[2]; };
    
    template <typename T, size_t N> yes is_array_test(T (&arr)[N]);
    no is_array_test(...);
    
    #define IS_ARRAY(x) (sizeof(is_array_test(x))==sizeof(yes))
    

    【讨论】:

    • 我更喜欢 SFINAE(= 专用模板)而不是宏,但是,这种通用方法是可行的方法。
    • 嗯,是的。然而,这可用作编译时间常数。
    • MSN:专用模板也是如此。 ;-) 只有调用语法略有变化,理想情况下它看起来像 Boost 类型特征:is_array&lt;x&gt;::value
    • 好吧,你不能完全做到 is_array::value。您可以在模板函数中以通用方式执行 is_array::value ,我猜这就是您所指的。但我认为我们都知道如何以两种方式解决这个问题,所以我们都赢了!
    【解决方案4】:

    int x[10] 将始终分配在调用它的位置的堆栈上。 x 值永远无法更改。

    int *y 简单地声明一个指向内存的指针,指针值可以随时更改,没有任何限制。

    int *y 可以有任意值。意思是,它可以指向堆栈分配的内存或堆分配的内存。从技术上讲,它也可以指向无效的内存,但这没有任何意义。

    int x[10] 保证你总是指向一个有效的内存,你不必担心内存释放。

    使用 int* y 时,您必须担心它指向的内存。

    还请记住,您的 porgram 动态分配的内存越多,就越容易出现错误、泄漏、性能问题、分配\解除分配 asimetry 和许多其他类型的问题。

    【讨论】:

      【解决方案5】:

      它们是不同的类型。

      如何区分 int32 和 uint32,或者 uint32 和 char[4]?

      正确的想法是,它们相似的唯一方式是在某些上下文中(包括数组索引!),数组提升为指针。

      【讨论】:

        【解决方案6】:

        我刚刚在 g++ 4.5 C++0x 模式下尝试了 char 数组的等效项,但它不会让我同时定义

        template <typename T>void moresilly(const T v[],const char *description)
        

        template <typename T>void moresilly(const T *v,const char *description)
        

        它声称两者是同一类型。

        我有一个函数:

        template <typename T>void silly(const T & v,const char *description)
        {
            cout<<"size of "<<description<<" is "<< sizeof(T)<<endl;
            moresilly(v,description);
        }
        

        如果通过,它会正确获取数组的大小,如果通过,它会正确获取指针的大小,但是我不能更傻地使用来区分指针和数组,所以我不能从指向 n 个字符的指针中分辨出 4 个字符的数组。

        在 T[1]、T[2]、T[3] 等上有模板可能会起作用,但是已经有一篇文章说不同的编译器以不同的方式处理(或一些类似的情况),并且gnu 更喜欢 C++11 中的指针匹配。

        ... 稍后添加: 经过一些实验,我发现了一些在 g++ 4.5 中有效的东西

        template <typename T,size_t L>void moresilly(const T (&v)[L],const char *description)
        {
            cout<<description<<" is an array"<<endl;
        }
        template <typename T>void moresilly(const T *v,const char *description)
        {
            cout<<description<<" is a pointer"<<endl;
        }
        template <typename T>void moresilly(const T v,const char *description)
        {
            cout<<description<<" is a raw value"<<endl;
        }
        template <typename T>void silly(const T & v,const char *description)
        {
            cout<<"size of "<<description<<" is "<< sizeof(T)<<endl;
            moresilly(v,description);
        }
        

        以下工作正常

            silly("12345","immediate string of 5 characters plus zero");
            silly((const char *)"12345","immediate constant char pointer of 5 characters plus zero");
            char testarray[]="abcdef";
            silly(testarray,"char array of 6 characters plus zero");
        const char testarray2[]="abcdefg";
        silly(testarray2,"const char array of 7 characters plus zero");
        

        请注意,如果第一个函数是用“const T v[L]”而不是“const T (&v)[L]”定义的,它将不起作用,永远不会匹配任何东西。

        所以我解决了您的问题,但不要指望这可以在其他版本的编译器中工作,包括未来的编译器。这就是我讨厌 c++ 的原因。不知何故,该语言的定义如此不清楚,以至于编译器充满了不稳定的边缘情况。

        这是一个有用的技巧,我可能会使用它。

        【讨论】:

          猜你喜欢
          • 2019-10-27
          • 2017-07-16
          • 1970-01-01
          • 2012-01-24
          • 1970-01-01
          • 1970-01-01
          • 2017-02-12
          • 1970-01-01
          • 2017-01-30
          相关资源
          最近更新 更多