У меня есть пара объектов class A
. В некоторых других class B
я хочу сохранить unordered_set объектов class A
. Обратите внимание, что объекты class B
, таким образом, содержат набор, который может указывать на (некоторые) те же самые объекты class A
, что и другой набор. Требуется, чтобы эти объекты class A
никогда не копировались или что-либо еще, поскольку они содержат данные членов, которые должны использоваться и изменяться (совместно используемые) различными объектами class B
и class A
.
Во-первых, поскольку я пришел из C, я думал просто использовать указатели на объект в качестве значений в наборе. Однако при написании кода я увидел, что теперь мне нужно также передать функции переопределенного хеширования и равенства, поскольку я должен сравнивать объекты класса A на предмет равенства в частном члене class A
. Таким образом, функция хеширования должна быть общедоступной функцией-членом class A
.
Однако мне было интересно, поскольку std::unordered_set::insert()
, похоже, берет ссылку на value_type, можно ли просто использовать A в качестве типа значения для std::unordered_set
. Это сделало бы код немного проще, поскольку по умолчанию он будет использовать == operator
, уже реализованный в class A
. Однако я не уверен, копирует ли std::unordered_set::insert()
объекты, которые вы ему передаете. Вроде нет, но value_type остается A, а не A&.
Я также не вижу разницы между std::unordered_set::insert()
и std::unordered_set::emplace()
. Я не понимаю, что означает «копировать против перемещения».
TLDR: чтобы сохранить ссылки на объекты определяемых пользователем классов в наборе или карте, возможно ли в этом случае использовать A*
как value_type? Или std::reference_wrapper<A>
? Или просто A
?
Вот минимальный воспроизводимый пример:
class A {
public:
bool operator== (A& other);
private:
B* b;
size_t id;
size_t someIntThatMustBeShared;
};
class B {
public:
std::unordered_set<A ? > as;
};
std::reference_wrapper
. Итак, прежде чем вы начнете размышлять о том, какой вариант лучше, похоже, вам нужно еще немного поучиться, вот. - person Sam Varshavchik   schedule 28.03.2020std::reference_wrapper
. Вы хорошо заметили, что это неясно из исходного вопроса, я отредактирую его. При этом я хотел бы подчеркнуть, что я не ищу какого-либо общего наилучшего решения, но я считаю, что предоставил достаточно конкретный пример использования, чтобы запросить конкретное решение в all, так как я не могу найти тот, который работает в любом случае. Вы советуете мне продолжать попытки с reference_wrapper? Это предпочтительный шаблон в данном случае? - person Adriaan Jacobs   schedule 28.03.2020A::someIntThatMustBeShared
при вставке черезstd::unordered_set::insert()
? Я предполагаю, что изменение этого целого числа в скопированном объекте не будет отражено во всех других копиях объекта. - person Adriaan Jacobs   schedule 28.03.2020std::unordered_set
, посколькуstd::reference_wrapper<T>
, похоже, не вызываетoperator ==
на своем<T>
. Итак, я писал тот же код, что и при использовании указателей. Тогда я спросил себя, в чем смысл, и не упускаю ли я из виду какое-то простое решение этой (думаю, не такой уж редкой) проблемы, используя, например, фактический объект в качестве ключа и динамически выделяя все члены. - person Adriaan Jacobs   schedule 29.03.2020std::shared_ptr
, который позволяет избежать прямого использования указателей. Вот почему я написал: C++ — самый сложный из используемых сегодня языков программирования общего назначения. Каким бы ни был лучший подход к показанному коду, это совершенно, совершенно и совершенно неуместно и бессмысленно. Потому что, как только вы измените одну строку показанного кода, лучший подход, скорее всего, будет другим. Вы должны решить это на основе вашего всего кода. - person Sam Varshavchik   schedule 29.03.2020class A
имеет целое число, которое должно обновляться несколько раз, из множество источников (под этим я подразумеваю, что целое число может быть доступно через ссылку на объект, который содержится в наборе где угодно). Поскольку вы подтвердили, чтоstd::unordered_set::insert()
копирует аргумент, какstd::unordered_set::emplace()
ведет себя по-другому? Предлагает ли это решение? - person Adriaan Jacobs   schedule 29.03.2020A
(внутренние, потому что мне нужен доступ к закрытым членам для их реализации). Однако я борюсь с проблемой кругового включения, и я не могу объявить внутренние классы. Я действительно думаю, что для этого должен быть шаблон проектирования, но я не могу правильно выполнить поиск в Google. - person Adriaan Jacobs   schedule 29.03.2020std::shared_ptr
, но я, должно быть, неправильно понял, как они работают, потому что казалось, что мне все еще нужно было предоставить свой собственный хэшер и эквалайзер, чтобы использовать их вstd::unordered_set
. - person Adriaan Jacobs   schedule 29.03.2020std::shared_ptr
и обычного указателя. - person Sam Varshavchik   schedule 29.03.2020