Класс с делегирующими конструкторами
class A {
A(SomeObject obj, // requires a new copy of the object
int x,
const string& y
) { // additional logic }
A(SomeObject obj, const string& y)
:A(obj, 0, y) {} // will obj be copied?
};
Целевое использование:
SomeObject obj;
A a1(obj, "first");
A a2(obj, "second");
План состоит в том, чтобы построить SomeObject
ровно один раз, когда выполняется построение A
. Приведет ли передача obj
к созданию копии другого SomeObject
при делегировании другому конструктору? Если да, то как мне этого избежать?
2 ответа
Да, obj
копируется при делегировании другому конструктору: это недопустимый контекст для copy elision или даже для автоматического перемещения.
Решение состоит в том, чтобы применить std::move
к аргументу в списке инициализаторов членов или (для частный целевой конструктор) получает объект не по ссылке - const
. Любой из них позволяет (общедоступному) конструктору по-прежнему получать свой аргумент по значению, как и рекомендация C ++ 11.
Нет. Он не копируется из одного конструктора в другой . Кажется, вы исходите из предположения, что один конструктор инициализирует объект, а затем передаст его другому, что не так. См. Эту цитату из стандарта:
Список-инициализатор-память может делегировать другому конструктору класса конструктора, используя любой тип class-or-decltype, который обозначает сам класс конструктора. Если mem-initializer-id обозначает класс конструктора, он должен быть единственным mem-инициализатором; конструктор - это делегирующий конструктор, а конструктор, выбранный mem-initializer, является целевым конструктором. Целевой конструктор выбирается по разрешению перегрузки. Как только целевой конструктор возвращается, тело делегирующего конструктора выполняется. Если конструктор делегирует самому себе прямо или косвенно, программа имеет неправильный формат, и диагностики не требуется.
Этот минимальный пример показывает, что Copied
печатается только один раз:
#include <iostream>
struct Foo {
Foo() = default;
Foo(const Foo&) {
std::cout << "Copied";
}
};
struct A {
A(Foo f, int i) { }
A(Foo f) : A(f, 0) { }
};
int main() {
A a{Foo{}};
}
Новые вопросы
c++
C ++ - это язык программирования общего назначения. Первоначально он был разработан как расширение C и имеет аналогичный синтаксис, но теперь это совершенно другой язык. Используйте этот тег для вопросов о коде (который должен быть) скомпилирован с помощью компилятора C ++. Используйте тег для конкретной версии для вопросов, связанных с конкретной версией стандарта [C ++ 11], [C ++ 14], [C ++ 17], [C ++ 20] или [C ++ 23] и т. Д. .