Обновить
129
0
Григорий Демченко@gridem

Software Engineer

Отправить сообщение
Ага, пришла пора обновиться. Спасибо за ответ.

Кстати, MSVC 11 CTP NOV12 выдает:
__thiscall B::B(void)
__thiscall B::B(const struct B &)
__thiscall B::B(const struct B &)
__thiscall B::~B(void)
__thiscall B::~B(void)
__thiscall B::~B(void)
Можете привести пример, когда они генерятся автоматически? Вот мой пример:

#include <iostream>

#define F			{std::cout << __PRETTY_FUNCTION__ << std::endl;}

struct B
{
	B() F
	~B() F
	B(const B&) F
	B(B&&) F
	B& operator=(const B&) F
	B& operator=(B&&) F
};

struct A
{
	B b;
};

int main()
{
	A a1;
	A a2(a1);
	A a3(std::move(a2));
	return 0;
}


Вывод:
B::B()
B::B(const B&)
B::B(const B&)
B::~B()
B::~B()
B::~B()

Если же реализовать так:
struct A
{
	A()=default;
	A(A&&)=default;
	B b;
};

То:
B::B()
B::B(const B&)
B::B(B&&)
B::~B()
B::~B()
B::~B()

Компилятор GCC 4.5.2
Наверно нечетко выразился. Я имел ввиду не те 4 старых, а 2 новых, с move-семантикой.
С move-семантикой и && иногда случаются недоразумения. Первая проблема — это то, что теперь вместо 4-х методов класса по-умолчанию получается 4 + 2 дополнительных (опциональных), но если мы хотим воспользоваться move-семантикой, то должны их объявить. Проблема тут в том, что даже если все члены класса поддерживают move-семантику, такие методы не генерируются компилятором автоматически. Т.е. надо явно написать:

class A
{
public:
    A(A&& a) = default;
    void operator=(A&& a) = default;
private:
    std::vector<int> myVec;
};

Тут спасает, конечно, новые навороты, типа =default, но душу это как-то не сильно греет.

Проблема номер 2 связана с тем, что для конкретных типов оптимизация && не применяется. Объясню на примере: предположим, что у нас есть класс A, который требует строку в качестве входного значения:
class A
{
public:
    A(const std::string& name_) : name(name_) {}
private:
    std::string name;
};

Если мы вызываем так: A(«my_name»), то тогда создается временный объект std::string, а затем происходит копирование и уничтожение. Казалось бы, тогда надо создавать так:
class A
{
public:
    A(std::string&& name_) : name(std::move(name_)) {}
private:
    std::string name;
};

Тогда вышеприведенный пример работает, однако такой — нет:
std::string name = "my_name";
A a(name);

Тогда мы приходим к тому, что надо 2 метода: один с const&, другой — c &&. Уже попахиваем мазохизмом. А если мы добавим в конструктор еще пару полей, типа std::string nick, std::string address, то тогда можно сразу бежать за валерьянкой. Спасает способ, приведенный в статье:
class A
{
public:
    template<typename T>
    A(T&& name_) : name(std::forward(name_)) {}
private:
    std::string name;
};

Но это, как бы так помягче сказать, для особых ценителей искусства. В общем, пока в новом стандарте радуют только лямбды.
Мне кажется, тут что-то перепутали. Правильное начало: британские ученые установили, что…
Наверно имелась ввиду дешевизна по отношению к ноутбукам. Хотя да, для России назвать это «дешевым» несколько натянуто.
А почему не использовали лямбду из нового стандарта? Она отлично ложится на использование в boost::asio и код получается проще и читабельней.
Безусловно, язык С справляется на 100% если речь идет про драйвера и низкоуровневые вещи. Я про другое. Про то, что на данный момент С является одним из самых непереносимых языков. Наверно, по непереносимости его переплюнет лишь ассемблер. Другие языки хорошо себя чувствуют на разных платформах. Просто С — он всеядный, т.е. доступен на огромном количестве платформ, и это иногда путают с переносимостью. Те же драйвера всегда пишутся под конкретную платформу и ось, что говорит о слабой переносимости. Каждый язык хорош для своих задач. Просто спецификация того, что char может быть 8-битным, а может быть и нет, говорит о том, что язык стараются адаптировать под различные платформы, а переносимость, т.е. портируемость этого кода на другие плафтормы, от этого лишь страдает.
Из википедии:
Портируемость (переносимость, англ. portability) обычно относится к одной из двух вещей:
1. Портируемость — как возможность единожды откомпилировав код (обычно в некоторый промежуточный код, который затем интерпретируется или компилируется во время исполнения, «на лету», англ. Just-In-Time), затем запускать его на множестве платформ без каких-либо изменений.
2. Портируемость — как свойство программного обеспечения, описывающее, насколько легко это ПО может быть портировано. По мере развития операционных систем, языков и техники программирования, становится всё проще портировать программы между различными платформами. Одной из изначальных целей создания языка Си и стандартной библиотеки этого языка — была возможность простого портирования программ между несовместимыми аппаратными платформами. Дополнительные преимущества в плане портируемости могут иметь программы, удовлетворяющие специальным стандартам и правилам написания (см., например: Smart Package Manager).

Вот теперь мне хочется понять, какой из пунктов для C легко реализуется?
Ну вот пример: у меня есть файлы на диске file.1, file.2,… file.1000000. Мне надо пройтись по всем файлам и показать контент. Каждый файл, например, занимает 10 байт (хотя это не принципиально). Как это сделать переносимо по стандарту?
А если данные итерируются на диске или еще где-нибудь? Ведь я не говорил, что данные в памяти.
Согласно стандарту size_t позволяет проитерировать миллион элементов?
Как sizeof поможет решить, какой тип использовать? Например, мне нужно проитерировать миллион элементов. Как, используя sizeof и без дефайнов мне написать такой цикл «переносимо»?
C переносимый, поэтому в нём базовые целочисленные типы (char, short, int и др.) не имеют строго установленного размера, а зависят от платформы.

То, что C переносимый — это миф. Может раньше он и был таковым, но сейчас — увы. Вышепреведенная фраза очень похожа на следующую: «в целях заботы о пользователях мы поднимаем плату за обслуживание». Спасибо, не надо.

Интересно, много ли на свете программистов, которые хотели бы, чтобы они не знали размеры базовых типов? Наверно, это чтобы было быстро? Т.е. лучше быстро и глючно? Наверно поэтому практически любая библиотека включает в себя configure — чтобы переносилось, ведь это ж часть языка, т.к. язык все может, ведь он переносим, да? А обилие #define тоже наверно говорит о великолепной переносимости? А то, что стандартные библиотеки не могут кроссплатформенно открыть, например, pipe — это тоже говорит о великолепной переносимости. В общем, заявление о том, что для поддержки переносимости нет определенности — это, извините, к доктору. Если хочется переносимости, то тогда надо все четко специфицировать, как, например, в Java. И не надо лохматить бабушку.
Такими темпами дело может дойти до биржи, и там будут торговать программистами как фьючерсами.
Было бы неплохо указать явно, что это — перевод.
Лучше так: ждем напечатанного на 3D принтере 3D принтер.
Как правило, это разработчик, и его цель — покрытие кода юнит-тестами. А это значит, что скорее всего, юнит-тест будет весьма не полным

С тем же успехом можно написать, что цель разработчика — сделать бажный продукт, т.к. я не видел еще не разу продукта без багов. Тут многое зависит от менеджера и опытности программиста, а говорить «как правило» — несколько надуманно. Как правило, юнит тесты вообще не пишутся.

В общем, культура TDD — это не написание тестов для галочки, а написание всевозможных сценариев для проверки. И автор забыл упомянуть такой подход: нашли баг — напиши юнит тест, чтобы этот баг не всплыл обратно. После этого юнит тесты заиграют новыми красками.
Не знаю, я вот наоборот считаю: купил iPhone — значит ты сектант и зомби, который не разбирается в технике и тупо хавает то, что дают.
Это совсем не тот старый добрый XCOM. Хоть бы название сменили с XCOM: enemy unknown. Вводит в заблуждение, что это ремейк той игры.

Информация

В рейтинге
Не участвует
Дата рождения
Зарегистрирован
Активность