Предположим, у меня есть следующее:
#include <memory>
struct A { int x; };
class B {
B(int x, std::unique_ptr<A> a);
};
class C : public B {
C(std::unique_ptr<A> a) : B(a->x, std::move(a)) {}
};
Если я правильно понимаю правила С++ о «неуказанном порядке параметров функции», этот код небезопасен. Если второй аргумент конструктора B
создается сначала с помощью конструктора перемещения, то a
теперь содержит nullptr
, а выражение a->x
вызовет неопределенное поведение (вероятно, segfault). Если первый аргумент построен первым, то все будет работать как задумано.
Если бы это был обычный вызов функции, мы могли бы просто создать временную:
auto x = a->x
B b{x, std::move(a)};
Но в списке инициализации класса у нас нет возможности создавать временные переменные.
Предположим, я не могу изменить B
, есть ли способ сделать это? А именно разыменование и перемещение unique_ptr
в одном и том же выражении вызова функции без создания временного?
Что, если бы вы могли изменить конструктор B
, но не добавлять новые методы, такие как setX(int)
? Это поможет?
Спасибо
B
, вам не нужно ничего этого делать. Просто используйте один аргумент,unique_ptr<A>
, и сделайте копиюa->x
в списке инициализации конструктора. - person Praetorian   schedule 18.07.2014B
таким образом, чтобы поддерживать это конкретное использование. Инициализацияx
с помощьюa->x
может оказаться неожиданной и, следовательно, не должна требовать особого случая отB
. Это зависит от контекста, но для конструктора, принимающего толькоunique_ptr
, может быть более естественным инициализироватьx
некоторой константой по умолчанию вместоa->x
. Если мы изменимB
на ссылкуunique_ptr
по rvalue, мы дадим вызывающим абонентам больше гибкости бесплатно и не изменим интерфейс. Я не вижу причин, по которым аргументunique_ptr
должен передаваться здесь по значению. - person Matthew Fioravante   schedule 18.07.2014B
и добавить перегрузку, которая принимает толькоunique_ptr<A>
. В этом случае подразумевается, чтоB
инициализируетx
изa->x
. Какой из них вы выберете, действительно зависит от предполагаемого использования вашего класса. - person Praetorian   schedule 18.07.2014