В чем недостаток, если я использую объекты в стеке, а не в куче в шаблоне фабрики? - PullRequest
0 голосов
/ 06 мая 2020
Коды

CPP следующие:

Operation* OperationFactory:: CreateOperation(char opr) {
OperationAdd resultAdd;
OperationSub resultSub;
OperationMul resultMul;
OperationDiv resultDiv;
switch (opr) {
case '+':
    return &resultAdd;
case '-':
    return &resultSub;
case '*':
    return &resultMul;
case '/':
    return &resultDiv;
default:
    break;
}}

Я обнаружил, что при попытке изменить поля объектов, созданных этой фабрикой, возникают некоторые ошибки.

Ответы [ 2 ]

1 голос
/ 06 мая 2020

Указатели, которые вы возвращаете, бесполезны после возврата из функции. Аналогичная проблема в более простом коде:

int* dont_do_this(){
    int x = 0;
    return &x;
}

x больше не существует, если функция вернула и у вас есть висячий указатель. Разыменование вызывает неопределенное поведение.

Это можно исправить, сделав x static:

int* maybe_do_this() {
    static int x = 0;
    return &x;
}

Теперь x сохраняется между вызовами функций. Однако, даже если вы исправите это, ваша «фабрика» всегда будет возвращать указатели на одни и те же объекты. Если это то, чего вы хотите, вам вообще не понадобится фабрика. Предполагается, что фабрика создаст экземпляры и вернет их:

std::unique_ptr<Operation> OperationFactory:: CreateOperation(char opr) {
    switch (opr) {
        case '+':
            return std::make_unique<OperationAdd>();
        case '-':
            return std::make_unique<OperationSub>();
        // ...
        default:
            return std::make_unique<OperationDefault>();
    }
}

Также вам нужно позаботиться о том, чтобы вернуть что-то во всех ветвях, и вы должны фактически использовать интеллектуальные указатели вместо необработанных указателей.

1 голос
/ 06 мая 2020

Привет и добро пожаловать в StackOverflow!

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

Надеюсь, что вы помогли!

Я бы предложил использовать std::unique_ptr<> или другой тип, который управляет уничтожением объекта, потому что если клиент не освобождает эту память, вы можете вызвать утечку памяти!

...