Мне хотелось бы знать, какие правила применяются, что приводит к промежуточный объект "elision".
Я создал этот минимальный пример, чтобы проиллюстрировать возможный вопрос.
Код: Выделить всё
#include
#include
class To {
public:
To() { std::puts("default constructor"); }
explicit To(int input) : val(input) { std::puts("value constructor"); }
// noexcept is a sweet lie because of std::puts
To(To&& object) noexcept : val(object.val) {
std::puts("move constructor");
}
// noexcept is a sweet lie because of std::puts
To& operator=(To&& object) noexcept {
val = object.val;
std::puts("move assign");
return *this;
}
~To() noexcept { std::puts("destructor"); }
private:
int val = -1;
};
class From {
public:
explicit From(int input) : val(input) {
std::puts("From value constructor");
}
// marking explicit to inhibit to1 assignement
operator To() const&& { return To{val}; };
private:
int val = -1;
};
To Make_To(int val) { return To{val}; }
int main() {
std::puts("-----------------");
std::puts("# direct init with conversion");
const std::tuple tp0{From{0}};
std::puts("# direct init with creator");
const std::tuple tp1{Make_To(1)};
std::puts("# init and assign");
std::tuple tp2;
tp2 = From{2};
std::puts("# finish");
}
(я использую C++17 для гарантированного RVO).
Вывод:< /p>
Код: Выделить всё
-----------------
# direct init with conversion
From value constructor
value constructor
# direct init with creator
value constructor
move constructor
destructor
# init and assign
default constructor
From value constructor
value constructor
move assign
destructor
# finish
destructor
destructor
destructor
Почему есть ли разница между инициализацией из преобразования и инициализацией из создателя?
[EDIT] расширенный пример
Вместо std::tuple я теперь использую простую оболочку:
Код: Выделить всё
struct Wrapper {
Wrapper(To&& Input) : val(Input) {
std::puts("Wrapper from To&& constructor");
};
Wrapper(const To& Input) : val(Input) {
std::puts("Wrapper from const To& constructor");
};
private:
To val;
};
int main() {
std::puts("-----------------");
std::puts("# Wrapper direct init with conversion");
const Wrapper d0(From{0});
std::puts("# Wrapper direct init with creator");
const Wrapper d1(Make_To(1));
std::puts("-----------------");
std::puts("# finish");
}
Теперь результат:
Код: Выделить всё
-----------------
# Wrapper direct init with conversion
From value constructor
value constructor
copy constructor
Wrapper from To&& constructor
destructor
# Wrapper direct init with creator
value constructor
copy constructor
Wrapper from To&& constructor
destructor
-----------------
# finish
destructor
destructor
Подробнее здесь: https://stackoverflow.com/questions/782 ... rmediate-o