Могу ли я убедиться, что только ссылочная переменная может принимать результат функции?

#c

#c

Вопрос:

Допустим, у меня есть эта функция

 class Entity;

Entityamp; CreateEntity(){
    Entity* e = new Entity();
    entityVec.emplace_back(e);
    return *e;
}
  

В настоящее время оба приведенных ниже кода будут скомпилированы.

 Entity a = CreateEntity();
Entityamp; b = CreateEntity();
  

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

Другими словами, есть ли какой-либо способ Entity a = CreateEntity() вызвать ошибку, и только Entityamp; b = CreateEntity() разрешено?

Если нет, есть ли какой-либо способ или шаблон, который может обеспечить его выполнение?

Спасибо.

Комментарии:

1. Можете ли вы объяснить, как ваша функция каким-то образом преобразовала указатель в ссылку? e это an Entity * , так как же ему удалось стать an Entity amp; ?

2. Вероятно, они забыли a * в теле функции.

3. Возможно ли, что вы хотите отключить построение / назначение копирования? Похоже, это может быть то, о чем вы думаете.

4. Ну, вы всегда можете удалить конструктор копирования, однако это предотвратит помещение этих объектов в вектор. Я подозреваю, что это проблема XY, и вы спрашиваете, как предотвратить копирование этих объектов. Если да, то у меня плохие новости: они уже постоянно копируются, поскольку помещаются в вектор. В любом случае, нет никакого способа сделать строго то, что вы просите. C так не работает.

5. @SamVarshavchik В коде OP это указатель , который помещается в вектор, поэтому удаленная копия ctor не будет беспокоить этот конкретный случай.

Ответ №1:

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

Анализ кода Microsoft может быть тем, что вы ищете: https://devblogs.microsoft.com/cppblog/new-safety-rules-in-c-core-check/https://learn.microsoft.com/en-us/cpp/code-quality/c26820?view=vs-2019

Если вы контролируете класс, о копировании которого беспокоитесь, вот возможное решение. Обходной путь — просто удалить конструкторы копирования /operator= . Я написал макрос, который делает именно это:

 // Disallow the use of the copy constructor and copy assignment operator for a class:
// Note: prefer to place this in public for better compiler error messages (Scott Meyers Effective C  )
#define UTIL_DELETE_COPY_AND_ASSIGN(udt)       
    udt(const udtamp;)             = delete; 
    udtamp; operator =(const udtamp;) = delete;
  
 class foobar
{
public:
    UTIL_DELETE_COPY_AND_ASSIGN(foobar);
}
  

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

 class foobar
{
public:
    foobar DeepCopy(); {...}
    UTIL_DELETE_COPY_AND_ASSIGN(foobar);
}