Различия в создании объектов - PullRequest
0 голосов
/ 08 июня 2011

В чем разница между двумя следующими способами для создания объекта?

Test* t = new Test();

и

Test* t;

Ваши ответы на второй пример совпадают с тем, что я думал, что это будет делать (объект не создается) Но

class Test {
        public:
                void bla(void) {
                        std::cout << "test" << std::endl;
                };
};

int main(void) {
        Test* test;
        test->bla();
}

дает мне вывод "test" ... Так что на самом деле есть Object

Ответы [ 7 ]

7 голосов
/ 08 июня 2011

Первый делает 4 вещи:

  • создает указатель на Test
  • выделяет память и создает Test объект (обратите внимание, что это Test, а не test)
  • новый объект инициализируется значением из-за () - см. Есть ли в скобках после имени типа разница с новым? для получения дополнительной информации
  • инициализирует указатель для указания на созданный объект

Второй просто создает указатель на Test.И он не инициализирован.


@ yogi - для вашего редактирования - это полностью Неопределенное поведение , так как указатель неинициализирован.И нет, это не объект.См. Функция C ++, вызываемая без инициализации объекта для получения дополнительной информации.

4 голосов
/ 08 июня 2011

Второй объект вообще не создает никаких объектов, и попытка доступа к нему приведет к плохим вещам ™.

2 голосов
/ 08 июня 2011

Это указатель, размещенный в стеке и использующий 32 или 64 бита памяти.

Test * t;

Это создаст объект типа Test в куче (и вам нужно удалить его из памяти)

t = new Test();

Это создаст объект типа Test в стеке (нет необходимости удалять его из памяти. Он исчезнет, ​​как только вы выйдете из текущего контекста)

Test t2;

Редактировать

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

1 голос
/ 08 июня 2011

После вашего обновления: причина, по которой он все еще успешно вызывает bla (), - просто неопределенное поведение.Потому что это именно то, что стандарт C ++ определяет, что происходит, когда вы работаете с небезопасной памятью (в данном случае это некоторый произвольный адрес, на который указывает ваш указатель) - поведение не определено.

1 голос
/ 08 июня 2011

Первый - это метод для создания экземпляра объекта.

Второй - это не метод для создания экземпляра объекта.Он просто объявляет указатель, который остается неинициализированным.

0 голосов
/ 08 июня 2011

Как уже говорили другие, вам просто повезло, что вызванное вами неопределенное поведение выглядит так, как вы ожидали (по сути, потому что ваш Test :: bla () почти похож на глобальную свободную функцию). Чтобы увидеть ваш пример сбоев и прожигов, просто добавьте несколько нетривиальных членов класса:

class Test {
public:
  void bla(void) {
    std::cout << "test: " << x << std::endl;
  };
  int x;
};

Вы можете представить свой оригинальный пример как бесплатную функцию

void bla(Test * p) { std::cout << "test" << std::endl; }

, который вы просто вызываете с параметром мусора, но поскольку вы не используете этот параметр, ничего плохого не происходит. В моем модифицированном примере мы пытаемся получить доступ к p->x и умереть.

0 голосов
/ 08 июня 2011
 Test* test;         
 test->bla(); 

Как уже говорилось в других ответах, Test* test не создает никаких объектов. Это неинициализированный указатель на Test. Он не указывает ни на что действительное, если он не инициализирован для указания на действительный объект Test.

Разыменование неинициализированного указателя, как вы, приводит к неопределенному поведению .
В вашем случае он не падает, потому что вы не ссылаетесь на this внутри bla().
Тем не менее, его до сих пор не определено поведение разыменования test.

Чтобы повторить вышеприведенный пункт, следующий пример в основном завершится сбоем.

#include<iostream>
class Test 
{
    public:
        int i; 
        void bla(void) 
        {
            std::cout << "test" << std::endl;
            std::cout << "test->i" << this->i <<std::endl;
        }
};

int main(void) 
{
    Test* test;
    test->bla();
    return 0;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...