Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
template <typename T>
void swap(T &first, T &second)
{
T tmp = std::move(first);
first = std::move(second);
second = std::move(tmp);
}
swap реализовывать xor'ами даже в случае простых типов, т.к. он не будет работать, если оба аргумента будут ссылками на одну и ту же переменную.int t = a;
a = b;
b = t;
mov eax, [a]
mov edx, [b]
mov [b], eax
mov [a], edxa ^= b;
b ^= a;
a ^= b;
mov eax, [a]
mov edx, [b]
xor eax, edx
xor edx, eax
xor eax, edx
mov [a], eax
mov [b], edxСамое плохое, что С++ идет куда-то не туда. Страуструп и Ко пытаются догнать современные языки по количеству модных плюшек, имея за спиной тяжеленный груз совместимости.
сейчас это не очень популярно.
auto может быть ситуация аналогичная var в C#.var. B::f — это просто другой метод с тем же именем, перегруженный, а не переопределенный
И снова это две перегруженные, а не переопределенные функции
// Или, сравним С++03 и С++11
// C++03
for (std::vector<std::map<int, std::string>>::const_iterator it = container.begin(); it != container.end(); ++it)
{
// do smth
}
// C++11
for (auto it = container.begin(); it != container.end(); ++it)
{
// do smth
}
auto container;
for (auto it = container.begin(); it != container.end(); ++it)
{
// do smth
}auto container;
foo(std::shared_ptr<int>(new int(42)), seed());
Besides symmetry with make_shared, make_unique offers at least two other advantages.мне тоже не понятно.
unique_ptr<T>(p) не бросает исключений, т.е. noexcept;shared_ptr<T>(p) может бросить std::bad_alloc при невозможности выделить дополнительную память в куче для счетчика ссылок и может бросать implementation-defined исключения при других ошибках.If A is not sequenced before B and B is not sequenced before A, then A and B are unsequenced. [ Note: The execution of unsequenced
evaluations can overlap. — end note ] Evaluations A and B are indeterminately sequenced when either A is sequenced before B or B is sequenced before A, but it is unspecified which. [ Note: Indeterminately sequenced evaluations cannot overlap, but either could be executed first. — end note ]
When calling a function (whether or not the function is inline), every value computation and side effect associated with any argument expression, or with the postfix expression designating the called function, is sequenced before execution of every expression or statement in the body of the called function. [ Note: Value computations and side effects associated with different argument expressions are unsequenced. — end note ]
Value computations and side effects associated with different argument expressions are unsequenced.
class B
{
public:
virtual void f(int) = 0;
};
class D : public B
{
public:
virtual void f(int) override {std::cout << "D::f" << std::endl;}
};
Ключевое слово virtual опционально и поэтому немного затрудняло чтение кода, заставляя вечно возвращаться в вершину иерархии наследования, чтобы посмотреть объявлен ли виртуальным тот или иной методЛюбая приличная IDE выделяет виртуальные методы, независимо от использования ключевого слова
virtual в наследниках.class Foo
{
static const int myConst = 0xB00B5;
};
была возможна и в С++03.assert(this != &temp); // assert if this is not a temporary
не имеет смысла, т.к. this все равно может оказаться temp, а проверить это нет возможности.if(this != &temp)
{
// 1. освобождаем ресурсы, занятые этим объектом
_buffer = nullptr;
// 2. берем данные из temp
_size = temp._size;
_buffer = std::move(temp._buffer);
_name = std::move(temp._name);
// 3. присванивание чего-либо temp будет препятствовать тому, чтобы деструктор
// освободил ресурсы, ранее занимаемые этим объектом
// temp._buffer = nullptr; <-- нет необходимости из-за использования std::move
temp._size = 0; // <-- в этом, соответственно, тоже нет необходимости
}
return *this;
auto объявить рекурсивную функцию, например факториал?auto fact(long long n)
{
return (n == 1)? 1: n * fact(n - 1);
}
swap, оператор присваивания копии в последнем примере можно переписать следующим образом:Buffer& operator=(Buffer copy)
{
swap(*this, copy);
return *this;
}
// ...
void swap(Buffer& first, Buffer& second) noexcept
{
using std::swap;
swap(first._name , second._name);
swap(first._size , second._size);
swap(first._buffer, second._buffer);
}
std::map<std::string, std::vector<int>> map;
for(auto it = begin(map); it != end(map); ++it)
{
// do smth
}
std::map<std::string, std::vector<int>> map;
for(auto it = map.begin(); it != map.end(); ++it)
{
// do smth
}
std::begin и std::endauto на std::function. А на самом деле можно сделать понятнее:auto fib = [&fib](int n) -> int {return n < 2 ? 1 : fib(n-1) + fib(n-2);};
Они больше не экспортируют свои перечисляемые значения в окружающую область видимости, больше не преобразуются неявно в целый тип и могут иметь определенный пользователем тип (эта опция так же добавлена и для «традиционных» перечислений").
#include <iostream>
enum class __enum : int { one = 0 };
int main () {
std::cout << static_cast<int>(class __enum::one) << std::endl;
return 0;
}
#include <iostream>
union __union final {
const int i;
};
int main () {
using foo = const union ::__union;
foo un = { .i = 0 };
std::cout << un.i << std::endl;
return 0;
}
struct __struct final {
__struct (const value&&) = default;
__struct (const value&) = delete;
};
#include <iostream>
constexpr int foo() {
return 1;
}
int main() {
int array[foo() + 1] = {0, 1};
std::cout << std::boolalpha << (array[0] < array[1]) << std::endl;
return 0;
}
namespace std {
template <typename __type, typename ...__arguments>
inline std::unique_ptr<__type> make_unique_helper (std::false_type, __arguments &&...arguments)
{
return std::unique_ptr<__type>(new __type(std::forward<__arguments>(arguments)...));
}
template <typename __type, typename ...__arguments>
inline std::unique_ptr<__type> make_unique_helper (std::true_type, __arguments &&...arguments)
{
using unique = typename std::remove_extent<__type>::type;
return std::unique_ptr<__type>(new unique[sizeof...(__arguments)] {
std::forward<__arguments>(arguments)...
});
}
template <typename __type, typename ...__arguments>
inline std::unique_ptr<__type> make_unique (__arguments &&...arguments) {
return make_unique_helper<__type>(std::is_array<__type>(),
std::forward<__arguments>(arguments)...);
}
}
template <typename T>
struct find_equal : std::binary_function <T, T, bool>
{
find_equal(const T &value) : value(value) {};
bool operator()(const T &left, const T &right) const {
return left == value && right == value;
}
private:
T value;
};
file.erase(std::unique(file.begin(), file.end(), ::find_equal<char>(' ')), file.end());
file.erase(std::unique(file.begin(), file.end(), [](const char &left, const char &right) {
return left == value && right == value;
}), file.end());
существует много новых дополнений к языку и стандартной библиотеке, эта статья лишь поверхностно охватывает часть из них.Обо всех возможностях можно книгу писать, в статью уж точно не уместится
enum class __enum: int { one = 0 };
union __union final {
struct __struct final {
template <typename __type, typename ...__arguments>
Each name that contains a double underscore _ _ or begins with an underscore followed by an uppercase letter (2.12) is reserved to the implementation for any use.
Функция, объявленная как final, не может быть переопределена функцией F::f() — в этом случае, она переопределяет метод базового класса (В) для класса D.
auto избавить от написания перегруженных функций?///...
typedef unsigned char T_1b; /* 1 byte unsigned */
typedef unsigned short T_2b; /* 2 byte unsigned */
typedef unsigned int T_4b; /* 4 byte unsigned */
typedef unsigned long long T_8b; /* 8 byte unsigned */
unsigned long long на auto никто и не советовал, размер кода это сократит, а вот читаемости поубавит, typedef'ами в таких случаях, по-моему, пользуются из покон веков. В Qt, к примеру, об этом изначально позаботились, и ранее обозначенный тип записывается как quint64. auto — это, в первую очередь, для работы с итераторами (ну и с лямбдами, разумеется)
Десять возможностей C++11, которые должен использовать каждый C++ разработчик