Этот хороший код? (скопируйте конструктора и оператор присваивания),

Последовательности в postgresql являются безопасной транзакцией. Таким образом, можно использовать

currval(sequence)

Кавычка:

Возврат currval

значение последний раз получено nextval для этой последовательности на текущей сессии. (Об ошибке сообщают, если nextval никогда не называли для этой последовательности на этой сессии.) Замечают, что, потому что это возвращает локальное для сессии значение, оно дает предсказуемый ответ, даже если другие сессии выполняют nextval между тем.

10
задан UmNyobe 1 July 2015 в 08:49
поделиться

6 ответов

Это плохо, потому что оператор = больше не может полагаться на установочный объект. Вы должны сделать это наоборот и использовать идиому копирования-обмена.

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

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

Fixture::Fixture():m_data(), m_size() { }

Fixture::Fixture(const Fixture& f) {
    m_data = new item[f.size()];
    m_size = f.size();
    std::copy(f.data(), f.data() + f.size(), m_data);
}

Fixture::~Fixture() { delete[] m_data; }

// note: the parameter is already the copy we would
// need to create anyway. 
Fixture& Fixture::operator=(Fixture f) {
    this->swap(f);
    return *this;
}

// efficient swap - exchanging pointers. 
void Fixture::swap(Fixture &f) {
    using std::swap;
    swap(m_data, f.m_data);
    swap(m_size, f.m_size);
}

// keep this in Fixture's namespace. Code doing swap(a, b)
// on two Fixtures will end up calling it. 
void swap(Fixture &a, Fixture &b) {
  a.swap(b);
}

Вот как я обычно пишу оператор присваивания. Прочтите Хотите скорости? Передача по значению о необычной сигнатуре оператора присваивания (передача по значению).

25
ответ дан 3 December 2019 в 13:35
поделиться

Сектор копирования и присваивание полностью различны - присваивание обычно требуется для освобождения ресурсов в объекте, который он заменяет, ctor копирования работает не -пока-инициализированный объект. Поскольку здесь у вас, по-видимому, нет особых требований (при назначении не требуется «освобождение»), ваш подход в порядке. В общем, у вас может быть вспомогательный метод «освободить все ресурсы, которые содержит объект» (который будет вызываться в dtor и в начале присвоения), а также часть «скопировать эти другие вещи в объект», которая достаточно близка к работе типичного копировщика (или в большинстве случаев; -).

8
ответ дан 3 December 2019 в 13:35
поделиться

Вы просто делаете поэлементное копирование и присваивание в своих примерах. Это не то, что вам нужно писать самому. Компилятор может генерировать неявные операции копирования и присваивания, которые делают именно это. Вам нужно только написать свой собственный конструктор копирования, присваивание и / или деструктор, если созданные компилятором не подходят (например, если вы управляете каким-либо ресурсом с помощью указателя или чего-то подобного)

6
ответ дан 3 December 2019 в 13:35
поделиться

Я думаю, вы столкнетесь с проблемами, если ваш оператор operator = когда-нибудь станет виртуальным.

Я бы порекомендовал написать функцию (возможно, статическую), которая делает копию, а затем имеет конструктор копирования и оператор = вызовите эту функцию вместо этого.

3
ответ дан 3 December 2019 в 13:35
поделиться

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

В книге Джеймса Коплиена 1991 года Advanced C ++ это описано как часть «Ортодоксальной канонической формы». В нем он выступает за конструктор по умолчанию, конструктор копирования, оператор присваивания и деструктор.

В общем, вы должны использовать ортодоксальную каноническую форму, если:

  • Вы хотите поддержать присваивание объекта класса, или хотите передать эти объекты в качестве параметров вызова по значению функции, и
  • Объект содержит указатели на объекты, которые подсчитываются по ссылкам, или деструктор класса выполняет удалить в элементе данных объекта.

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

Коплиен предлагает страницы причин этого паттерна, и я не могу их полностью передать. Однако ключевой пункт, который уже был затронут, - это возможность очистить перезаписываемый объект.

Ключевой элемент, который уже был затронут, - это возможность очистить перезаписываемый объект.

Ключевой пункт, который уже был затронут, - это возможность очистить перезаписываемый объект.

2
ответ дан 3 December 2019 в 13:35
поделиться

Думаю, вы следует инициализировать переменные-члены вашего объекта, используя список инициализаторов . Если ваши переменные имеют примитивные типы , то это не имеет значения. В противном случае присваивание отличается от инициализации.


Вы можете сделать это с помощью небольшого трюка, инициализировав указатели внутри конструктора копирования на 0 , после чего вы можете безопасно вызвать delete в оператор присваивания :

Fixture::Fixture(const Fixture& f) : myptr(0) {
    *this = f;
}
Fixture& Fixture::operator=(const Fixture& f) {
    // if you have a dynamic array for example, delete other wise.
    delete[] myptr;
    myptr = new int[10];
    // initialize your array from the other object here.
    ......
    return *this;
}
1
ответ дан 3 December 2019 в 13:35
поделиться
Другие вопросы по тегам:

Похожие вопросы: