C++ 和 Java 中的动态对象数组有何不同?

how arrays of dynamic objects differs in C++ & Java?

我最近在 Java 中了解了对象数组。 考虑一下:

Student s[]=new student[3];

但是为什么上面的语句只创建了一个可以保存对 3 个学生对象的引用的数组。它不会自己创建学生 class 对象。我必须使用 Student class 的构造函数单独创建它们。所以如果我尝试像这样访问任何 class 成员:

s[0].name="meet"

会产生运行时错误"NullPointerException"

但这些对我来说似乎很奇怪,因为在 C++ 中这些不是必需的。 考虑这个 C++ 程序。

#include <iostream>
using std::cout;
class Test
{
    public:
        Test()
        {
            cout<<"Constructor\n";
        }
        void fun()
        {
            cout<<"fun() is called\n";
        }
        ~Test()
        {
            cout<<"Destructor\n";
        }
};
int main()
{
    Test* t=new Test[3];
    for(int i=0;i<3;i++)
        t[i].fun();
    delete[] t;
    return 0;
}

当 main() 中的第一个语句执行时内部会发生什么?如果它在 C++ 中工作正常那么为什么在 java.

中生成 NullPointerException
   class test
    {
          test()
          {
                 System.out.println("Constructor");
          }

          void fun()
          {
                 System.out.println("fun() is called");
          }
           public static void main(String args[])
           {
                 test t[]=new test[3];
                 for(int i=0;i<3;i++)
                       t[i].fun();  // oops runtime error
                 for(int i=0;i<3;i++)
                       t[i]=new test();
                 for(int i=0;i<3;i++)
                       t[i].fun();  // now fine.
           }

}

为什么在java中必须使用class的构造函数单独创建对象,而在C++中却不需要使用class的构造函数单独创建?

请帮助我。

简短的回答只是因为语法(几乎相同)并不意味着它的工作原理相同。实际上,由于 Student s[]

中的 [],您编写的语句不会在 C++ 中编译

与您的 Java 代码等效的 C++ 代码是:

Student** s = new Student*[3];

然后您可以像这样初始化学生:

s[0] = 新学生("Jimmy");

这是一个需要掌握的重要概念,因为 Java 并不是唯一以这种方式不同于 C++ 的编程语言。

这是一个完整的示例,您可以尝试一下。使用 g++ 4.3.2

编译
#include <iostream>
#include <string>

class Student {
public:
    Student() : name_("<unknown>") {
        std::cout << "Default constructor called" << std::endl;
    }
    Student(const char* name) : name_(name) {
        std::cout << "constructor called with name '" << name << "'" << std::endl;
    }
    void setName(const std::string& name) { name_ = name; }
    const std::string& getName() const { return name_; }

private:
    std::string name_;
};

void demoArrayOfValues() {
    std::cout << "demoArrayOfValues()" << std::endl;

    // Here the default constructor will be called 3 times because
    // creating you're creating an array of objects
    Student* s =  new Student[3];

    for (int x = 0; x < 3; ++x) {
        std::cout << "Student[" << x << "] (byValue): " << s[x].getName() << std::endl;
    }

    s[0].setName("Jimmy");
    s[1].setName("Sally");
    s[2].setName("Susie");

    for (int x = 0; x < 3; ++x) {
        std::cout << "Student[" << x << "] (after setting): " << s[x].getName() << std::endl;
    }

    std::cout << std::endl;
}

void demoArrayOfPointers() {
    std::cout << "demoArrayOfPointers()" << std::endl;

    // This is the C++ equivalent of the Java example that started the question
    // Here you're creating an array of pointers and have to create the objects
    // themselves
    Student** s =  new Student*[3];

    for (int x = 0; x < 3; ++x) {
        std::cout << "Student[" << x << "] (pointer): " << s[x] << std::endl;
    }

    s[0] = new Student("Jimmy");
    s[1] = new Student("Sally");
    s[2] = new Student("Susie");

    for (int x = 0; x < 3; ++x) {
        std::cout << "Student[" << x << "] (after creating): " << s[x]->getName() << std::endl;
    }

    std::cout << std::endl;

    // Now we iterate over the elements in the array and delete each one.       
    for (int x = 0; x < 3; ++x) {
        delete s[x];
    }

    // Now we delete the array itself
    delete [] s;
}

int main(int argc, const char** argv) {
    demoArrayOfValues();
    demoArrayOfPointers();

    return 0;
}