Чудеса С++: разные формы вызова конструктора копирования

Что происходит, когда мы пишем A a(3), A a = 3 и A a = A(3)? Меня этот вопрос давно интересовал. Конечно, у класса должны быть корректные конструкторы, в том числе и копирования, операторы присваивания и т.п.

Проведем следственный эксперимент...

#include <stdio.h>

class A
{
    public:
    A() 
    {
        printf("A::A()\n");
    }

    A(int) 
    {
        printf("A::A(int)\n");
    }

    A(int, int) 
    {
        printf("A::A(int, int)\n");
    }

    A(const A&amp; a) 
    {
        printf("A::A(const A&amp; a)\n");
    }

    void operator=(const A&amp; a) 
    {
        printf("A::operator=(const A&amp; a)\n");
    }
};

int main()
{
    printf("=&gt; A a1;\n");
    A a1;
    printf("=&gt; A a2(3);\n");
    A a2(3);
    printf("=&gt; A a3;\n");
    A a3 = 3;
    printf("=&gt; A a4 = A(3);\n");
    A a4 = A(3);
    printf("=&gt; A a5; a5 = A(3);\n");
    A a5; a5 = A(3);
    printf("=&gt; A a6(a1);\n");
    A a6(a1);
    printf("=&gt; A a7(4,4);\n");
    A a7(4, 4);
    printf("=&gt; A a8 = A(4,4);\n");
    A a8 = A(4, 4);
    return 0;
}

Выведет на экран:

=&gt; A a1;
A::A()
=&gt; A a2(3);
A::A(int)
=&gt; A a3;
A::A(int)
=&gt; A a4 = A(3);
A::A(int)
=&gt; A a5; a5 = A(3);
A::A()
A::A(int)
A::operator=(const A&amp; a)
=&gt; A a6(a1);
A::A(const A&amp; a)
=&gt; A a7(4,4);
A::A(int, int)
=&gt; A a8 = A(4,4);
A::A(int, int)

Т.е. каждый раз вызывается обычный конструктор и все три формы, приведённые в начале поста, эквивалентны.

Однако стоит нам конструктор копирования объявить private, и сразу же получим вот это:

[smir@smira Teaching]$ g++ test.cxx 
test.cxx: In function int main():
test.cxx:22: ошибка: A::A(const A&amp;) is private
test.cxx:39: ошибка: в данном контексте
test.cxx:22: ошибка: A::A(const A&amp;) is private
test.cxx:39: ошибка: в данном контексте
test.cxx:39: ошибка:   initializing temporary from result of A::A(int)
test.cxx:22: ошибка: A::A(const A&amp;) is private
test.cxx:41: ошибка: в данном контексте
test.cxx:22: ошибка: A::A(const A&amp;) is private
test.cxx:41: ошибка: в данном контексте

Строка 22 - это объявление конструктора копирования, а 39 и 41 это обращения A a3 = 3 и A a4 = A(3);. Интересно получается, что хотя конструктор копирования и не вызывается, но эти формы требуют его открытости. Это стандарт C++, оптимизация gcc или что-то ещё?

Как передать ощущение чуда другим?

Вот я знаю, что юнит-тесты и документирование кода - это чудо. Правда, это чудесные идеи, которые потрясающе повышают эффективность работы. Но это знаю я, я этим активно пользуюсь, не могу без этого уже работать.

Как объяснить это другим? Как их "зажечь" этой возможностью?

Ведь и то, и другое лень. На это нужно время... Объяснить на пальцах, что и то, и другое, экономит время, очень тяжело. Программисту кажется, что кроме выполнения его основных обязанностей - написания кода - его заставляют делать что-то ещё, что непосредственно не является видимым результатом его деятельности. Да, конечные пользователи продукта не увидят юнит-тестов и их совершенно не будет интересовать документация по коду. Но ведь эти средства позволяют (при грамотном использовании, конечно) улучшить качество продукта, а это конечные пользователи заметят, и именно это должно служить основной мотивацией для разработчика.

Мне кажется, что документация - это сродни чистоплотности, это то же самое, что и форматирование (оформление) кода, это ещё один аспект читаемости кода. Если я уважаю человека, который будет читать мой код, я должен его красиво оформить, снабдить комментариями. Ведь мы моемся, одеваем чистую одежду, чтобы другим людям не было противно с нами общаться. И здесь наш код - одежка, по которой нас встречают.

Так как всё-таки передать другим ощущение чуда? Мне кажется, очень важно показать пример, показать результат деятельности. Вот, смотри, давай построим документацию по коду - красота... Вот, этот модуль полностью отдокументирован и он выглядит так классно. А вот твой файл... Добавишь комментарии - и ведь он будет такой же! Юнит-тесты так же. Показать пример, как увеличивается скорость разработки от применения юнит-тестов!

Использование bitten для continuous integration

В связи с нашими разработками, в том числе кроссплатформенных приложений, я озаботился возможностью как-то организовать процесс компиляции, прохождения unit-тестов, различных артефактов разработки, например, документации по коду. Полезно иметь такую вещь: часть программистов использует Windows, там не все утилиты работают нормально или их настроить бывает непросто. Ну и оттестировать своё приложение нескольких архитектурах после каждого комита бывает непросто.

После небольшого осмотра того, что нам может предложить Internet из open-source проектов были отобраны кандидаты на роль continuous integration-средства:

Cruise Control самый сложный, вроде бы самый первый проект в этой области, с различными возможностями, настройками, плагинами и т.п. Но меня оттолкнула необходимость ставить Java, настраивать её, еще какой-нибудь Servlet-контейнер. BuildBot вроде бы работоспобен, но некрасивый (а это, по-моему, очень важно, средство должно быть не только удобным, но и красивым, это очень мотивирует на использование).

Мы очень активно в своих проектах используем Trac, а Bitten как раз с ним интегрирован, это подкупает. Он красивый, расширяемый, написан на питоне, а этот язык является одним из основных в нашей работе. Единственный минус - проект полузаброшенный, работающая версия - это trunk в репозитории, однако есть некоторый community, который достаточно активно пытается поддерживать проект. Всё это в сумме несмотря на указанный недостаток склонило чашу весов с сторону Bitten.

У нас Trac 0.10.x, Bitten установился без проблем, нужно было только заметить, что URL страницы с информацией выглядит как /build/, а вот клиент билда (buildslave) должен обращаться на /builds/ (легко промахнуться). У нас на траке была HTTP-авторизация, и пришлось для успешного коннекта buildslave поставить в апаче HTTP-авторизацию не только на URL /login/, но и на /builds/. После этого всё заработало без проблем, оставалось только настраивать последовательность команд для buildа проекта, архитектуры, запускать побольше buildslave на машинах с разной архитектурой.

В планах добавить побольше команд для рализличных вариантах buildа, парсинге результатов юнит-тестирования, code-coverage, архивирования артефактов (например, скомпилированных приложений, документации по коду).

Скриншоты

Страница со статусом билда

Настройка билда

Обо мне

Меня зовут Андрей Смирнов, я работаю техническим директором компании НетСтрим. Если говорить проще, я руковожу разработкой программных продуктов. Наша компания разработала много интересных проектов, например, LoadUp.

В этом блоге я собираюсь рассказывать о вещах, которые так или иначе связаны с программированием или с интересными событиями в моей жизни.

В качестве хобби я преподаю в Московском Государственном Университете им. М.В. Ломоносова на факультете Вычислительной математики и кибернетики.

Притча

Жила-была на свете высокая Гора, выше всех других гор на планете. Она была очень высокой, её шапку покрывал лед, и была эта гора безжизненной, потому что ни одно живое существо не могло выжить в таком холоде. И еще но небосводу этой планеты ходило Солнце, вставало и заходило день за днем... Солнце было высоко, оно свысока смотрело на свою планету, стараясь равномерно осветить каждый её уголок. И шло так тысячи и тысячи лет, день сменялся ночью, Гора была всё так же горда и высокомерна, осматривая местность вокруг себя, потому что она - самая высокая Гора. Солнце проходя по небсоклону не могло согреть Гору. И вот Солнце в один день поняло, что стареет. Такая уж судьба у звезд... они рождаются, молодеют, и потом стареют, не могут уже светить так же ярко. И стало Солнцу грустно... И показалась ему, что жизнь прошла зря, нет, оно выполняло свои обязанности исправно, светило ярко и ровно, но так никого по-настоящему и не согрело. И вот в этот момент Солнце оказалось как раз над Горой, и поглядело Солнце на планету, и увидело, что есть на ней самое близкое для него - Гора, ведь она была самой высокой горой. И обратилось Солнце к Горе и сказало: "Я старею, Гора... Ты будешь еще долго стоять на этом самом месте, но у меня уже совсем немного сил осталось. Я скоро потухну, и останешься ты в темноте. Ты - самое близкое, что есть у меня на этой планете." И поднялась Гора, сбросила с себя вековую тоску, взглянуло на Солнце и ответило: "Я всегда смотрела на тебя, когда ты проходило по небосводу. Я радовался твоим первым лучам и засыпал вместе с твоими последними лучами, исчезающими за горизонтом. Ты - самое дорогое, что есть у меня. Я видел, как ты родилось, и увижу, как ты потухнешь. Я очень старая Гора, но есть у меня одна мечта". "Какая мечта?" - спросило Солнце. "Я такая большая и высокая Гора, что не было на мне никакой жизни. Освети меня ярко, согрей меня, я хочу, чтобы стало тепло". "Нет", сказало Солнце - "Я не хочу так. Я не хочу, чтобы ты видела, как я потухну, я просто однажды зайду за горизонт и ты меня больше не увидишь. Да и тяжело тебе будет, когда я тебя сначала согрею, а потом потухну". Гора же ответила только одно: "Я хочу быть с тобой". И тогда Солнце остановило свой ход, встало прямо над горой. Его жаркие лучи осветили Гору, растаял снег и лед на шапке Горы, ручьи побежали по согретым Солнцем склонам, и вот и тут, и там, через теплую почву начали пробиваться ростки травы, зазеленели склоны, на них выросли деревья, высокие и красивые, в эти леса прилетели птицы, они пели и услаждали слух Солнца и Горы. И Солнце поняло, что теперь оно видит цель своей жизни: оно сделало счастливой Гору, высокую и мрачную, теперь же Гора зеленая и прекрасная, на ней живут животные, летают птицы, цветут райские сады, полные диковинных цветов. Залюбовалось Солнце Горой, влюбилось Солнце в Гору, и Гора полюбила Солнце, потому что не было в их жизни лучше времени, чем когда они были вместе.

И Бог увидел это счастье, и подарил им жизнь. И радовалось Солнце, глядя на зеленую Гору, и Гора радовалась, глядя на жаркое и яркое Солнце, и так было всегда. Так родилась Любовь.

Звезда

Видишь, там на небе горит звезда?.. Нет, не та... Она одна из тысяч, одна из миллионов, но она та самая звезда. Ты её увидела? Смотри на неё внимательно, когда ночное небо ясное. Ты её увидешь, когда её будут заслонять облака, ты её увидишь и ярким солнечным днём, её свет только для тебя, он твой, а солнце и луна светят всем. Теперь ты её увидела? Смотри на неё не отрываясь, эта звезда будет вести тебя за собой.

Ты спросишь, а ведь вчера была другая звезда, кто-то мне показывал совсем в другую сторону неба, и говорил идти за ней. Ну, оглянись, посмотри, где эта звезда? На небосклоне не бывает двух твоих звезд одновременно, предыдущая померкла, растворилась в тысячах других рядом. Не обманывай себя, выключи лампы, потуши свечи, это не звезды, ты не можешь зажечь звезду сама.

Ты боишься, что и эта померкнет? Но откуда ты знаешь, что так произойдет? Да, предыдущие падали с небосклона, оставляя за собой хвост светящихся искр. Но ты не знаешь, сколько гореть этой звезде, и у тебя нет другой сейчас, поэтому не думай об этом, иди к ней, чем ты ближе, тем ярче её свет...

Я больше не скажу ничего... Дальше ты сама... Если захочешь, бери меня за руку, мы пойдем вместе к ней, я знаю дорогу...

Друг друга

Они ходили рядом в толпе, не замечая друг друга, иногда они касались друг друга, но расходились в разные стороны. И вдруг... очередное касание... они повернулись друг к другу лицом, взглянули в глаза друг другу... И тогда они поняли, что были рядом всегда, мыслями, делами они были где-то близко. Одного взгляда хватило, чтобы они крепко взяли друг друга за руки и никогда больше не отпускали...

Это всё ты

Шелест листвы, тихое дыхание ветра, золотые зайчики предзакатного солнца, сочный запах молодой листвы, тишина соснового леса, громкий стук дождя по окну, темное ночное небо, полное звезд, первый лучик восходящего солнца, скрип свежевыпавшего снега - это всё ты. Нежное дыхание, глубокий взгляд, милый голос, ласковое прикосновение - это всё ты. Сжимающееся сердце, ожидание, тоска - и это тоже всё ты. Ощущение счастья, желание жить, красивые мечты, красочные сны - и это всё ты. Новый день, первое, что я увижу, проснувшись, первое, о чем я подумаю, - это всё ты. Мои мысли, чувства, желания, стремления - это всё ты.

И... и это тоже всё ты.

Птица счастья

Птица счастья, дай я ухвачу тебя за хвост! Я столько разных птиц принимал за тебя, думал, что это ты, хватался за них, но понимал, что ошибся. Но теперь-то ты меня не проведешь, я уже почувстсвовал твоё дыхание, дыхание счастья, настоящего счастья. Я вижу как переливаются перья на твоей груди, вижу взмах твоих крыльев. Еще одна попытка, еще прыжок, я хватаюсь за тебя, но в моей руке остается только перо из твоего хвоста, которое быстро блекнет, будучи оторванным от твоего тела. Но знай, ты от меня не улетишь на этот раз... На этот раз ты моя!

Солнце

Небо голубое, ярко светит солнышко... Хочу взять тебя за руку, обнять и пойти с тобой вперед, по бесконечной ледяной глади... Насколько хватает глаз перед нами снег, яркий, белый снег, от солнца тепло... Мы с тобой идём, взявшись за руки, и постепенно наши фигуры становятся всё меньше и меньше на фоне безоблачного неба. Мы идём туда, где небо и земля сходятся в одной точке, там, на краю горизонта, где есть только ты и я, наше счастье и голубое небо, и где ярко-ярко светит солнце.

Contents © 2015 Andrey - Powered by Nikola