Это действительно просто: то, как вы его используете, Tp
рассматривается как значение. Неважно, что это может быть указатель, поскольку указатели являются значениями. Вы можете думать о указателе как intptr_t
с некоторыми добавленными дополнениями. Итак, makeObj
делает экземпляр указателем . Но этот указатель ни на что не указывает. Итак, obj->data = 10
- неопределенное поведение. И с этого момента ваш код может делать что угодно. На этом анализ заканчивается. Вам нужно исправить makeObj
. Я предполагаю, что makeObj
должна быть фабричной функцией.
Ниже приведен пример того, как makeObj
может выглядеть. Вы действительно не хотите возиться с необработанными указателями. Заводские функции должны возвращать std::unique_ptr
или эквивалент (например, kj::Own
из capnproto ). Вот как должен выглядеть идиоматический современный C ++.
Вам также не нужно использовать консольный ввод-вывод для подтверждения того, что все работает должным образом: вы можете assert
, и отладчик остановится в точке, гдеутверждение не удается. От этого до разработки, основанной на тестировании, есть небольшой шаг;вы бы использовали вариант «assert», который специфичен для используемой тестовой среды. Но даже без тестовой среды легко проверить вещи, используя assert, когда вы играете с вещами.
Учитывая, что мы живем в прекрасные времена, когда вы можете получить доступ к компилятору и отладчику C ++ в браузере, выможете поэкспериментировать с кодом ниже на https://onlinegdb.com/BJZOB6gKH
#include <cassert>
#include <memory>
template <class T, class... Args> std::unique_ptr<T> makeObj(Args &&... args) {
auto ptr = std::make_unique<T>(std::forward<Args>(args)...);
ptr->data = 10;
return ptr;
}
struct MyType {
int foo = {};
int data = {};
MyType() = default;
MyType(int foo, int data) : foo(foo), data(data) {}
};
int main()
{
auto t = makeObj<MyType>(5, 20);
assert(t->foo == 5);
assert(t->data == 10);
auto u = makeObj<MyType>();
assert(u->foo == 0);
assert(u->data == 10);
}