2

if i declare an array without mentioning its size on visual studio code or other online compiler then it works fine but if i use same code in visual studio then it does not work. i know its not correct to declare unknown size array but just due to condition of not using pointer or any other thing, i had to use it. On visual studio, when i made only link and webpage class then i worked.

Can anyone tell me how to do this.

#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);
}

On visual studio, when i made only link and webpage class then i worked.

12
  • 3
    you cannot declare an array without its size Commented Jul 29, 2020 at 18:23
  • 1
    Try using pointers. link * links = nullptr; links = new links[2048]; Commented Jul 29, 2020 at 18:24
  • You should elaborate more on why the proper alternatives to this won't work for you. The body of your constructor (the wpgs[#]; statements) also does nothing at all. Commented Jul 29, 2020 at 18:24
  • 5
    A better solution is to use a std::vector. Example: std::vector<link> links; links.push_back(hyperlinks[i]); Commented Jul 29, 2020 at 18:25
  • This is a feature of c that c++ does not have: https://en.wikipedia.org/wiki/Flexible_array_member Commented Jul 29, 2020 at 18:27

4 Answers 4

2

Use C++ containers or pointers.

  1. I recommend using std::vector, std::list, ...
  2. Pointer: link* links, then use new link[100] where needed, and delete[] links
  3. Smart pointers: shared_ptr<link[]> sp(new link[10]);
Sign up to request clarification or add additional context in comments.

1 Comment

std::list<> is rarely a good idea because it tends to lead to poor performance since your cache locality is shot to hell.
2

As a comment notes, this is https://en.wikipedia.org/wiki/Flexible_array_member

The Windows API uses this in technique in a few places. Consequently Visual Studio supports this with C++ as noted in https://learn.microsoft.com/en-us/cpp/cpp/arrays-cpp?view=vs-2019

A zero-sized array is legal only when the array is the last field in a struct or union and when the Microsoft extensions (/Ze) are enabled.

The trick with using this technique however is that whoever creates the object also has to allocate memory following it for the non-sized array to extend into. Otherwise using that array results in corrupting memory that's being used for other purposes.

So using it the way you did is incorrect. It's only by chance that your program didn't show bizarre behavior or crash.

As a comment notes, you should use std::vector or another such container that fits your needs.

Comments

1

A non-static member array cannot have an unspecified size. Only static arrays can be declared to have an unspecified size. The size must then be specified in the definition, and it will still be compile time constant.

If what you need is an array of runtime size, then the array needs to be allocated dynamically. Simplest solution is to use std::vector.

it works fine but

Regardless, the program is ill-formed. When an ill-formed program compiles, it is usually because you are using a language extension. When you use a language extension, the program won't work with compilers that do not implement the same extension.

One should avoid using language extensions in order to keep the program portable.

Comments

-1

I have a investigated the problem a bit and just found out its a horrible mess of c++ design or may be extension design(whatever you say).

Just look at the code below(it works fine):

#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;
}

Now, just look at another code segment below with a few change(It does not run at all):

#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;
}

Its the same, when using new operator in place of malloc().

What I'm trying to imply is that, it's a very bad design decision of compiler(or, compiler extension of cpp language). You shouldn't write your code in this structure.

You may use vector, list or your own data structure whatever you wish, would still be a better choice than whatever you're doing now. Vector would be the most efficient solution though.

[P.S.]: As stated above, you can see this to understand, why some compilers can compile your code, while some can't.

I have tested using mingw.

4 Comments

The main problem with this answer is that int buf[]; is not legal C++.
Yeah, I know that, but it works fine with mingw compiler, which shouldn't even compile. So, I have tried to explain, what could be the outcome if someone code using that invalid yet working feature.
OK granted, but the OP seems has used a flexible array in his code above, has realised that it doesn't compile with Visual Studio and so is looking for another solution. Unfortunately given the restrictions he has placed on himself that other solution does not exist.
Yes, it seems so. (S)he would understand it the hard way may be :D.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.