Advertisement
Guest User

c++11 features

a guest
Oct 6th, 2016
80
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.57 KB | None | 0 0
  1. #include <iostream>
  2. #include <cstring>
  3. #include <vector>
  4.  
  5. template<typename T>
  6. class Array {
  7. private:
  8.     std::vector<T> data_;
  9. public:
  10.     explicit Array(size_t n, T val = T()): data_(n, val) {}
  11.     /* конструктор, принимающий список инициализации */
  12.     // Array(std::initializer_list<T> l): data_(l) {}
  13. };
  14.  
  15.  
  16. /* пример С-структуры */
  17. struct Point {
  18.     int x, y;
  19. };
  20.  
  21. /* посмотрим на конструкторы чего-то похожего на std::string
  22.  * нет 0-ого символа в конце, хотим просто взглянуть на конструкторы */
  23. class String {
  24. public:
  25.     String() {
  26.         data_ = new char[1];
  27.         data_[0] = '\0';
  28.     }
  29.  
  30.     String(const char *s) {
  31.         size_t len = strlen(s);
  32.         data_ = new char[len + 1];
  33.         memcpy(data_, s, len + 1);
  34.     }
  35.  
  36.     /* конструктор копирования */
  37.     String(const String& s) {
  38.         std::cout << "copy ctor of String\n";
  39.         size_t len = s.size();
  40.         data_ = new char[len + 1];
  41.         memcpy(data_, s.data_, len + 1);
  42.     }
  43.  
  44.     /* конструктор перемещения
  45.      * поскольку s ссылается на rvalue, может спокойно
  46.      * испортить объект, он все равно скоро будет уничтожен */
  47.     String(String&& s): data_(s.data_) {
  48.         std::cout << "move ctor of String\n";
  49.         s.data_ = nullptr;
  50.     }
  51.  
  52.     /* принимаем по значению, чтобы воспользоваться конструкторами
  53.      * если передавалось lvalue, то s будет сконструировано
  54.      * с помощью конструктора копирования, поэтому тут s - копия, никак не свяязанная
  55.      * с оригинальным объектом, можно делать с ней что угодно.
  56.      * Если передавалось rvalue, будет вызван конструктор перемещения,
  57.      * т.е. s.data_ по сути указывает на бывшую память временного объекта, поэтому сам s снова
  58.      * больше не нужен */
  59.     String& operator=(String s) {
  60.         std::cout << "operator = of String\n";
  61.         delete[] data_;
  62.         data_ = s.data_;
  63.         s.data_ = nullptr;
  64.         return *this;
  65.     }
  66.  
  67.     ~String() {
  68.         if (data_ != nullptr)
  69.             delete[] data_;
  70.     }
  71.  
  72.     size_t size() const {
  73.         return strlen(data_);
  74.     }
  75. private:
  76.     char *data_;
  77. };
  78.  
  79. void anotherFunc(String&& s) {
  80.     std::cout << "got rvalue in anotherFunc\n";
  81. }
  82.  
  83. void anotherFunc(const String& s) {
  84.     std::cout << "got lvalue in anotherFunc\n";
  85. }
  86.  
  87. /* T&& не является rvalue-ссылкой, можно это называть универсальной ссылкой
  88.  * (см. способы вызова)
  89.  * аргументы функций - ВСЕГДА lvalue (можем взять адрес)
  90.  * хотим получить rvalue, если в месте вызова было передано rvalue
  91.  * и lvalue в противном случае. Это и делает std::forward.
  92.  * Это позволяет осуществлять perfect forwarding - передачу аргументов дальше
  93.  * ровно в том виде, в котором они были переданы */
  94. template<typename T>
  95. void someFunc(T&& arg) {
  96.     anotherFunc(std::forward<T>(arg));
  97. }
  98.  
  99. class StringWrapper {
  100. public:
  101.     StringWrapper(const String& s): str_(s) {}
  102.     StringWrapper(const StringWrapper& s): str_(s.str_) {
  103.         std::cout << "copy ctor of StringWrapper\n";
  104.     }
  105.     /* как уже говорилось, аргументы всегда являются lvalue
  106.      * но мы тут имеем ссылку на rvalue, поэтому хотим сделать
  107.      * s.str_ rvalue - это и делает std::move */
  108.     StringWrapper(StringWrapper&& s): str_(std::move(s.str_)) { // вызов конструктора перемещения
  109.         std::cout << "move ctor of StringWrapper\n";
  110.     }
  111.  
  112.     StringWrapper& operator=(StringWrapper s) {
  113.         std::cout << "operator = of StringWrapper\n";
  114.         str_ = std::move(s.str_);
  115.         return *this;
  116.     }
  117. private:
  118.     // StringWrapper(const StringWrapper& s) = delete; // пример удаления конструктора копирования
  119.     String str_;
  120. };
  121.  
  122. String returnSomeString() {
  123.     return "123";
  124. }
  125.  
  126. /* вычисления на этапе компиляции
  127.  * замена страшным решениям с помощью шаблонов
  128.  * constexpr функции должны содержать только один return
  129.  * в C++14 требование ослабили */
  130. constexpr int pow(int a, int b) {
  131.     return b == 0 ? 1 : a * pow(a, b - 1);
  132. }
  133.  
  134. int main() {
  135.     Point p = {1, 2}; // инициализация в стиле С простых структур
  136.     /* теперь можно использовать фигурные скобки и для вызова обычных конструкторов
  137.      * внутри таких конструкторов запрещены небезопасные приведения типов
  138.      * например size_t в int, long long в double и т.д. */
  139.     Array<int> a{5u, 3};
  140.     std::vector<int> v = {1, 2, 3}; // вызов конструктора от std::initializer_list
  141.     /* конструктор от списка инициализации всегда имеет приоритет при вызове через {}
  142.      * поэтому здесь создается вектор из 1-ого элемента 7 */
  143.     std::vector<int> v2{7};
  144.  
  145.     String s("abc");
  146.     StringWrapper w(s);
  147.     StringWrapper w1(w); // конструктор копирования
  148.     StringWrapper w2 = std::move(w); // делаем w rvalue, вызывается конструктор перемещения
  149.  
  150.     StringWrapper w3(s);
  151.     w1 = w3;
  152.     w2 = std::move(w3);
  153.  
  154.     /* вызов функции, принимающей универсальную ссылку */
  155.     someFunc(s); // вызов с lvalue, T = string& , type of arg = string&
  156.     someFunc(returnSomeString()); // вызов с rvalue, T = string, type of arg = string&&
  157.  
  158.     constexpr int n = 7;
  159.     int some_array[pow(3, n)]; // вычисляется на этапе компиляции
  160.     return 0;
  161. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement