Прямая инициализация из определяемого пользователем преобразования оптимизирует промежуточный объект.C++

Программы на C++. Форум разработчиков
Ответить Пред. темаСлед. тема
Гость
 Прямая инициализация из определяемого пользователем преобразования оптимизирует промежуточный объект.

Сообщение Гость »

Я искал способ инициализировать кортеж и нашел это опубликованное решение, основанное на преобразовании между классами.
Мне хотелось бы знать, какие правила применяются, что приводит к промежуточный объект "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");
}
Live C++17
(я использую 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
Я разрешаю создание и назначение в качестве ссылки для ситуации, когда RVO не может полностью применяться в качестве целевого объекта, поскольку срок его существования уже начался.
Почему есть ли разница между инициализацией из преобразования и инициализацией из создателя?

[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
Это сильно отличается от версии std::tuple, хотя я ожидал того же результата. Как это так?

Подробнее здесь: https://stackoverflow.com/questions/782 ... rmediate-o
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «C++»