В чем разница между CCow *cow = new CCow(); и CCow cow;?

В чем разница между вот этим: "CCow *cow = new CCow()" и этим: "CCow cow".

Cow.h


#pragma once

#include <string>

class CCow
{
  public:
    void ObtainCowInfo();
    void DisplayCowInfo();

  private:

    std::string mName;
    int mAge;
};

Cow.cpp


#include "Cow.h"
#include <iostream>

using namespace std;

void CCow::DisplayCowInfo()
{
  cout << endl;
  cout << "Cow Info" << endl;
  cout << "+++++++++++++++" << endl;
  cout << "Name: " << mName << endl;
  cout << "Age: " << mAge << endl;
  cout << "+++++++++++++++" << endl << endl;
}

void CCow::ObtainCowInfo()
{
  cout << "Type Cow Information" << endl;
  cout << "--------------------" << endl;
  
  cout << "Cow's name: ";
  cin >> mName;

  // Inputting the cow's age, until valid input is inputted
  bool exit = false;
  while(!exit)
  {
    cout << "Cow's age: ";
    cin >> mAge;
    
    if(!mAge)
    {
      // We have an error
      cout << "Invalid age, try again" << endl; 
      cin.clear();
      cin.ignore(); 
      continue;
    }

    exit = true;     
  }
  cout << endl;
}

Main.cpp


#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include "Cow.h"
#include <vector>

using namespace std;

vector<CCow*> mCowListPointer; 
vector<CCow> mCowsList;

void Test1(int loop)
{
  for(int i = 0; i < loop; i++)
  {
    CCow *cow = new CCow();
    cow->ObtainCowInfo();
    mCowListPointer.push_back(cow);
  }

  cout << "Result:" << endl;
  for(auto animal : mCowListPointer)
  {
    animal->DisplayCowInfo();
  }
}

void Test2(int loop)
{
  for(int i = 0; i < loop; i++)
  {
    CCow cow;
    cow.ObtainCowInfo();
    mCowsList.push_back(cow);
  }

  cout << "Result:" << endl;
  for(auto animal : mCowsList)
  {
    animal.DisplayCowInfo();
  }
}

int main()
{
  int loop = 0;
  cout << "Input loop number: ";
  cin >> loop;
  cout << endl;

  Test1(loop);
  cout << "####################" << endl;
  Test2(loop);
  

  return 0;
}


Ответы (1 шт):

Автор решения: AlexGlebe

В реализации класса vector предусмотрено дополнительное выделение памяти у системы для новых элементов.

v.size() == 2
v.capacity() == 4 
v[0] == obj0 
v[1] == obj1 
v[2] == место для объекта
v[3] == место для объекта

и при добавлении нового элемента у системы не будет запрашиваться память, а только вызывается конструктор объекта.

Когда вы используете вектор указателей, для каждого элемента вы запрашиваете у системы память и это очень сильно будет тормозить систему.

Чтобы ещё больше оптимизировать программу нужно написать конструктор копирования и перемещения объекта. Это даст ещё больше скорости, и память для строки std::string mName; будет не копироваться, а переноситься указателями.

CCow(CCow const & x):mName(x.mName),mAge(x.mAge){}
CCow(CCow && x):mName(std::move(x.mName)),mAge(x.mAge){}

и объект из стека будет перенесён без нагрузки на систему памяти.

mCowsList.push_back(std::move(cow));

Плюсы вектора объектов : меньше нагрузки на диспетчер памяти.

Плюсы вектора указателей : при постоянном увеличении размера вектора перенос указателей на новое место трудностей у системы не вызывает.

Минусы вектора объектов : при большом количестве объектов их размера и сложности возникают трудности переноса вектора на другой участок памяти (если постоянно добавляете). Происходит полный перенос всех объектов из старого места. Нужно всегда не забывать создавать конструкторы переноса. Чем больше объект, тем перенос дольше.

Минусы вектора указателей : постоянный вызов диспетчера памяти для нового участка памяти и если не забыли, то и освобождение памяти delete перед удалением указателей из вектора.

→ Ссылка