Порядок конструирования аргументов функции
Встретил статью «Пять подводных камней при использовании shared_ptr», в которой утверждается, что:
в строке кода:
foo( shared_ptr<Widget>(new Widget), bar() );
порядок конструирования не определен. Все зависит от конкретного компилятора и флагов компиляции. Например, это может произойти так:
- new Widget
- вызов функции bar
- конструирование shared_ptr
- вызов функции foo
Почему так? Я считал, что в списке параметров функции точки следования определены запятыми и аргументы (границы между которыми очерчивают запятые) действительно могут быть обработаны в любом порядке, НО каждый отдельный аргумент, если уж начал обрабатываться программой, то обрабатывается до конца. А т.к. shared_ptr<Widget>(new Widget)
- это отдельный аргумент, то он обработается целиком (т.е. в приведённом списке пункты 1 и 3 всегда будут идти подряд).
Разве не так? Ткните, пожалуйста, меня носом в "что бы прочесть", чтобы уяснить свою ошибку. Спасибо.
Обновление
@KoVadim, в статье рассматривается случай, когда выполнение bar()
бросает исключение. Тогда (исходя из предложенного порядка обработки аргументов) получается, что объект Widget
сконструирован, но shared_ptr
ещё нет (следовательно и не завладел объектом Widget
). Отсюда утечка памяти.
Обновление 2
@KoVadim, да, действительно, Вы правы. Дело именно в этом. Прочёл дальше комментарии к статье - там кто-то уже задал подобный вопрос. В ответ ему посоветовали ссылку http://www.gotw.ca/gotw/056.htm Тут разбирается подобный случай. А причина неопределённости, как Вы уже заметили, в том, что запятая, отделяющая параметры функции друг от друга - это разделитель (comma separator), а не оператор запятая (comma operator). А точкой следования из них является только оператор. Спасибо за пинок в правильном направлении.