【问题标题】:Declaring c++ array without size声明没有大小的 c++ 数组
【发布时间】:2020-07-29 18:21:51
【问题描述】:

如果我在 Visual Studio 代码或其他在线编译器上声明一个数组而没有提及它的大小,那么它可以正常工作,但如果我在 Visual Studio 中使用相同的代码,那么它就不起作用。 我知道声明未知大小的数组是不正确的,但只是由于不使用指针或任何其他东西的条件,我不得不使用它。 在 Visual Studio 上,当我只制作链接和网页类时,我就开始工作了。

谁能告诉我怎么做。

#include <iostream>
using namespace std;
class link
{
    const char* name;
public:
    link() :name("null")
    {
        cout<<"Default link constructor called"<<endl;
    };
    link(const char n[]) :name(n)
    {
        cout<< "Parameterized link constructor called"<<endl;
    };
};
class webpage
{
private:
    double height;
    double width;
    int linkno;
    link links[];
public:
    webpage() :height(10), width(10), linkno(2)
    {
        links[0]=NULL;
        links[1]=NULL;
    };
    webpage(double hw,int lno, link hyperlinks[]) :height(hw), width(hw),linkno(lno)
    {
        for (int i = 0; i < linkno; i++)
        {
            links[i]=hyperlinks[i];
        }
    };
    webpage(double h, double w,int lno, link hyperlinks[]) :height(h), width(w),linkno(lno)
    {
         for (int i = 0; i < linkno; i++)
        {
            links[i]=hyperlinks[i];
        }
    };
    void showdata(int linkno)
    {
        cout << "height: " << height << endl;
        cout << "width: " << width << endl;
        cout << "links " << endl;
        for (int i = 0; i < linkno; i++)
        {
            cout << "link #" << i + 1 << " = " << links[i].getname() << endl;
        }
    }
};
class website
{
private:
    const char* name;
    int webpageno;
    webpage wpgs[];
public:
    website() :name("null"),webpageno(4)
    {
        wpgs[0];
        wpgs[1];
        wpgs[2];
        wpgs[3];
    };
    website(const char n[],int wpn, webpage page[]) :name(n),webpageno(wpn)
    {
        for (int i = 0; i < webpageno; i++)
        {
            wpgs[i]=page[i];
        }
        
        cout<<"Parameterized website constructor called"<<endl;
    };
    void showdata(int linkno, int pageno)
    {
        cout << endl<< "Website name: " << name << endl;
        for (int j = 0; j < pageno; j++)
        {
            cout << "Webpage #" << j + 1 << " : " << endl;
            wpgs[j].showdata(linkno);
            cout<<endl<<endl;
        }
    }
};
int main(int argc, char* argv[])
{
  link link1[2]={"maha","saira"};
  webpage page[1]={{32,21,2,link1}};
    website site("my website",1,page);
    site.showdata(2,1);
}

在 Visual Studio 上,当我只制作链接和网页类时,我就开始工作了。

【问题讨论】:

  • 你不能声明一个没有大小的数组
  • 尝试使用指针。 link * links = nullptr; links = new links[2048];
  • 您应该详细说明为什么合适的替代方案对您不起作用。构造函数的主体(wpgs[#]; 语句)也什么都不做。
  • 更好的解决方案是使用std::vector。示例:std::vector&lt;link&gt; links;links.push_back(hyperlinks[i]);
  • 这是c的一个c++没有的功能:https://en.wikipedia.org/wiki/Flexible_array_member

标签: c++ arrays


【解决方案1】:

使用 C++ 容器或指针。

  1. 我推荐使用std::vector, std::list, ...
  2. 指针:link* links,然后在需要的地方使用new link[100],以及delete[] links
  3. 智能指针:shared_ptr&lt;link[]&gt; sp(new link[10]);

【讨论】:

  • std::list&lt;&gt; 很少是一个好主意,因为它往往会导致性能不佳,因为您的缓存位置被击中地狱。
【解决方案2】:

作为评论说明,这是https://en.wikipedia.org/wiki/Flexible_array_member

Windows API 在一些地方使用了这种技术。因此,Visual Studio 使用 C++ 支持这一点,如 https://docs.microsoft.com/en-us/cpp/cpp/arrays-cpp?view=vs-2019

中所述

仅当数组是结构或联合中的最后一个字段并且启用了 Microsoft 扩展 (/Ze) 时,零大小的数组才是合法的。

然而,使用这种技术的诀窍是,创建对象的人还必须在它之后分配内存,以便扩展非大小数组。否则使用该数组会导致正在用于其他目的的内存损坏。

因此,以您的方式使用它是不正确的。您的程序没有出现异常行为或崩溃只是偶然。

作为注释说明,您应该使用 std::vector 或其他适合您需要的容器。

【讨论】:

    【解决方案3】:

    非静态成员数组不能有未指定的大小。只有静态数组可以声明为具有未指定的大小。然后必须在定义中指定大小,它仍然是编译时常量。

    如果您需要的是一个运行时大小的数组,那么该数组需要动态分配。最简单的解决方案是使用std::vector

    效果很好,但是

    无论如何,该程序格式错误。当一个格式错误的程序编译时,通常是因为您使用了语言扩展。当您使用语言扩展时,程序将无法与未实现相同扩展的编译器一起使用。

    为了保持程序的可移植性,应避免使用语言扩展。

    【讨论】:

      【解决方案4】:

      我对这个问题进行了一些调查,发现它是一个可怕的 c++ 设计混乱,或者可能是扩展设计(不管你说什么)。

      看看下面的代码(它工作正常):

      #include <iostream>
      
      using namespace std;
      
      class Test {
      private:
          int n;
          int buf[];
      public:
          Test() : n(0) {}
          Test(int _n, int* _buf) : n(_n) {
              for(int i=0; i<n; i++) {
                  buf[i] = _buf[i];
              }
          }
          void print() {
              printf("array:");
              for(int i=0; i<n; i++) {
                  printf(" %d", buf[i]);
              }
              printf("\n");
          }
      };
      
      int main() {
          int n = 100;
          int b[128];
          for(int i=0; i<n; i++) {
              b[i] = i;
          }
          Test t = {n, b};
          t.print();
          return 0;
      }
      

      现在,看看下面的另一个代码段,有一些变化(它根本不运行):

      #include <iostream>
      
      using namespace std;
      
      class Test {
      private:
          int n;
          int buf[];
      public:
          Test() : n(0) {}
          Test(int _n, int* _buf) : n(_n) {
              for(int i=0; i<n; i++) {
                  buf[i] = _buf[i];
              }
          }
          void print() {
              printf("array:");
              for(int i=0; i<n; i++) {
                  printf(" %d", buf[i]);
              }
              printf("\n");
          }
      };
      
      int main() {
          int n = 100;
          
          // int b[128];
          
          // rather than declaring array
          // using dynamic memory allocation technique
          int *b = (int *)malloc(sizeof(int) * 128); // everything same, just this line is changed
          for(int i=0; i<n; i++) {
              b[i] = i;
          }
          
          Test t = {n, b};
          t.print();
          
          free(b);
      
          return 0;
      }
      

      同样,使用 new 运算符代替 ma​​lloc()

      我想暗示的是,这是一个非常糟糕的编译器设计决策(或者,cpp 语言的编译器扩展)。您不应该在这种结构中编写代码。

      您可以随意使用向量、列表或您自己的数据结构,这仍然是比您现在正在做的任何事情更好的选择。 Vector 将是最有效的解决方案。

      [P.S.]:如上所述,你可以看this来理解,为什么有些编译器可以编译你的代码,而有些则不能。

      我已经使用 mingw 进行了测试。

      【讨论】:

      • 这个答案的主要问题是int buf[];不是合法的C++。
      • 是的,我知道,但它与 mingw 编译器一起工作得很好,它甚至不应该编译。因此,我试图解释,如果有人使用该无效但有效的功能进行编码,结果可能是什么。
      • OK,但是 OP 似乎在上面的代码中使用了一个灵活的数组,已经意识到它不能用 Visual Studio 编译,因此正在寻找另一种解决方案。不幸的是,鉴于他对自己施加的限制,不存在其他解决方案。
      • 是的,看起来是这样。 (S)他会很难理解它可能是:D。
      猜你喜欢
      • 2020-03-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多