Object array initialization without default constructor

后端 未结 11 1938
误落风尘
误落风尘 2020-11-22 04:20
#include 
class Car
{
private:
  Car(){};
  int _no;
public:
  Car(int no)
  {
    _no=no;
  }
  void printNo()
  {
    std::cout<<_no<

        
相关标签:
11条回答
  • 2020-11-22 04:39

    I don't think there's type-safe method that can do what you want.

    0 讨论(0)
  • 2020-11-22 04:40

    No, there isn't. New-expression only allows default initialization or no initialization at all.

    The workaround would be to allocate raw memory buffer using operator new[] and then construct objects in that buffer using placement-new with non-default constructor.

    0 讨论(0)
  • 2020-11-22 04:43

    You can use placement-new like this:

    class Car
    {
        int _no;
    public:
        Car(int no) : _no(no)
        {
        }
    };
    
    int main()
    {
        void *raw_memory = operator new[](NUM_CARS * sizeof(Car));
        Car *ptr = static_cast<Car *>(raw_memory);
        for (int i = 0; i < NUM_CARS; ++i) {
            new(&ptr[i]) Car(i);
        }
    
        // destruct in inverse order    
        for (int i = NUM_CARS - 1; i >= 0; --i) {
            ptr[i].~Car();
        }
        operator delete[](raw_memory);
    
        return 0;
    }
    

    Reference from More Effective C++ - Scott Meyers:
    Item 4 - Avoid gratuitous default constructors

    0 讨论(0)
  • 2020-11-22 04:48

    You can always create an array of pointers , pointing to car objects and then create objects, in a for loop, as you want and save their address in the array , for example :

    #include <iostream>
    class Car
    {
    private:
      Car(){};
      int _no;
    public:
      Car(int no)
      {
        _no=no;
      }
      void printNo()
      {
        std::cout<<_no<<std::endl;
      }
    };
    void printCarNumbers(Car *cars, int length)
    {
        for(int i = 0; i<length;i++)
             std::cout<<cars[i].printNo();
    }
    
    int main()
    {
      int userInput = 10;
      Car **mycars = new Car*[userInput];
      int i;
      for(i=0;i<userInput;i++)
          mycars[i] = new Car(i+1);
    

    note new method !!!

      printCarNumbers_new(mycars,userInput);
    
    
      return 0;
    }    
    

    All you have to change in new method is handling cars as pointers than static objects in parameter and when calling method printNo() for example :

    void printCarNumbers_new(Car **cars, int length)
    {
        for(int i = 0; i<length;i++)
             std::cout<<cars[i]->printNo();
    }
    

    at the end of main is good to delete all dynamicly allocated memory like this

    for(i=0;i<userInput;i++)
      delete mycars[i];      //deleting one obgject
    delete[] mycars;         //deleting array of objects
    

    Hope I helped, cheers!

    0 讨论(0)
  • 2020-11-22 04:49

    Nope.

    But lo! If you use std::vector<Car>, like you should be (never ever use new[]), then you can specify exactly how elements should be constructed*.

    *Well sort of. You can specify the value of which to make copies of.


    Like this:

    #include <iostream>
    #include <vector>
    
    class Car
    {
    private:
        Car(); // if you don't use it, you can just declare it to make it private
        int _no;
    public:
        Car(int no) :
        _no(no)
        {
            // use an initialization list to initialize members,
            // not the constructor body to assign them
        }
    
        void printNo()
        {
            // use whitespace, itmakesthingseasiertoread
            std::cout << _no << std::endl;
        }
    };
    
    int main()
    {
        int userInput = 10;
    
        // first method: userInput copies of Car(5)
        std::vector<Car> mycars(userInput, Car(5)); 
    
        // second method:
        std::vector<Car> mycars; // empty
        mycars.reserve(userInput); // optional: reserve the memory upfront
    
        for (int i = 0; i < userInput; ++i)
            mycars.push_back(Car(i)); // ith element is a copy of this
    
        // return 0 is implicit on main's with no return statement,
        // useful for snippets and short code samples
    } 
    

    With the additional function:

    void printCarNumbers(Car *cars, int length)
    {
        for(int i = 0; i < length; i++) // whitespace! :)
             std::cout << cars[i].printNo();
    }
    
    int main()
    {
        // ...
    
        printCarNumbers(&mycars[0], mycars.size());
    } 
    

    Note printCarNumbers really should be designed differently, to accept two iterators denoting a range.

    0 讨论(0)
  • 2020-11-22 04:51

    My way

    Car * cars;
    
    // else were
    
    extern Car * cars;
    
    void main()
    {
        // COLORS == id
        cars = new Car[3] {
            Car(BLUE),
                Car(RED),
                Car(GREEN)
        };
    }
    
    0 讨论(0)
提交回复
热议问题