Функция-член C++ требует указателя, плохая практика для передачи по ссылке?

Если функция-член класса C++ требует указателя на объект в качестве аргумента, считается ли это плохой практикой для передачи по ссылке?

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

class ClassA
{
public:
    void SetPointer(const ClassB& classb) // Remove 1 ampersand and serious errors will occur
    {
        if(ptr_to_classb == nullptr) // Initialized to nullptr in constructor
            ptr_to_classb = &classb;
        else
            throw(...); // Throw some error
    }

private:
    ClassB* ptr_to_classb;
}

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

Альтернатива заключается в следующем:

class ClassA
{
public:
    void SetPointer(const ClassB* const classb)
    {
        if(ptr_to_classb == nullptr) // Initialized to nullptr in constructor
            ptr_to_classb = (ClassB*)(classb);
        else
            throw(...); // Throw some error
    }

private:
    ClassB* ptr_to_classb;
}

Мне нравится последовательность, по умолчанию для первого типа, однако я подозреваю, что вторая форма считается лучшей практикой. Это тот случай?

3 ответа

Хорошо, оба подхода верны и хороши, но в вашем случае, вероятно, будет лучше использовать указатели, так как ссылочной переменной может быть присвоено значение только при инициализации, в отличие от указателей. С тем же указателем вы можете позже передать другой объект класса.

На мой взгляд, если передача пустого аргумента в метод является допустимой вещью (то есть логика, которую выполняет метод, будет действительной с нулевым указателем), то используйте указатель. Если аргумент никогда не должен быть нулевым, используйте ссылку.

В вашем случае это зависит от того, действительно ли для ClassA::ptr_to_classb значение null. Так как вы бросаете, если ptr_to_classb уже установлен (то есть вы никогда не захотите изменять то, на что он указывает), вы можете даже рассмотреть возможность сохранения ссылки и передачи ее в конструктор ClassA, избавившись от ClassA::SetPointer.

Здесь есть и другие мнения относительно ссылки против указателя.

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

Мне нравится последовательность, чтобы по умолчанию первый тип

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

void do_stuff(ClassA& object)

обычно означает "делать что-то на объекте и забыть об этом", и ваш случай отличается.

Другие вопросы по тегам