Избегайте копии по значению при инициализации ссылки
-
25-10-2019 - |
Вопрос
У меня есть функциональный интерфейс:
struct iFace {
virtual Type& getType() = 0;
}
И идея состоит в том, чтобы получить это как:
iFace& iface = getIface();
Type& type = iface.getType();
Тем не менее, я иногда делаю ошибку и пишу:
Type type = iface.getType();
Какой копирует по цене, чего я хочу избежать. Однако, когда я делаю такие ошибки, компилятор не выдает предупреждение, потому что его легальный синтаксис. Я хотел бы запустить ошибку во время компиляции для этого, Вопрос Каковы мои альтернативы?
Я подумал о том, чтобы объявить конструктор копии, но нигде не определить, что приведет к ошибке времени, если она используется, но тогда я не смогу использовать конструктор копирования в ЛЮБЫЕ ситуация, которая меньше, чем достоверно
Решение
Сделайте iface не совместимым, поместив конструктор копирования и оператора назначения в «Private». Затем предоставьте явный метод копирования.
class Type {
public:
virtual Copy(Type& dest) = 0;
private:
Type (const Type &) {assert(false)}
Type & operator=(const Type &) {assert(false)}
}
Вы также можете использовать повысить некоррекцию сделать то же самое (это реализовано, как указано выше).
Так что, если вы хотите копировать ваш код, вы бы сделали
Type& type = iface.getType();
Type typeCpy;
type.Copy(typeCpy);
Кроме того, я бы добавил, что если вы делаете это из -за проблем с производительностью, вы уверены, что оптимизатор не избавится от временной копии для вас?
Другие советы
Возвращение указателя здесь кажется разумным, но если сбивает с толку, вы можете вернуть обертку вокруг ссылки.
struct Class {
struct Ref {
Ref(Class& c_) : c(c_) { }
Class Clone() { return c; }
// overload -> to provide access to c
private:
Class& c;
};
};
Оригинальный класс может копировать как обычно, но ссылка вы должны сделать явно. Я не в восторге от этой идеи (я бы меньше подумал о пользователе, который не понимал, как работает копия семантики, чем тот, кто случайно держался за один из них слишком долго), но теоретически это выполнимо.