Тип возврата шаблона со значением по умолчанию - PullRequest
4 голосов
/ 14 марта 2011

Таким образом, при написании шаблона класса C ++ я определил метод, который возвращает объект шаблонного типа, как таковой:

template <typename T>
class Foo
{
public:
    T GetFoo()
    {
        T value;

        //Do some stuff that might or might not set the value of 'value'

        return value;
    }
 };

int main() {

    Foo<int> foo;

    foo.GetFoo();

    return 0;
}

Это дает следующее предупреждение:

prog.cpp: In member function ‘T Foo<T>::GetFoo() [with T = int]’:
prog.cpp:15: warning: ‘value’ is used uninitialized in this function

Я понимаю, почему это происходит - я возвращаю неинициализированный int как часть GetFoo.Дело в том, что если бы я использовал Foo<SomeClass>, строка T value; инициализировала бы value с использованием конструктора по умолчанию SomeClass.

Мне удалось подавить это предупреждение, выполнив следующие действия:

    T GetFoo()
    {
        T value = T();

        //Do some stuff that might or might not set the value of 'value'

        return value;
    }

Похоже, это работает для примитивных типов (таких как int и float) и классов, по крайней мере, если у этого класса есть конструктор по умолчанию и конструктор копирования.Мой вопрос - это общепринятый способ решения этой проблемы?Есть ли побочные эффекты, о которых я должен знать?

Ответы [ 6 ]

5 голосов
/ 14 марта 2011

Звучит нормально, если у класса нет конструктора копирования, вы все равно не сможете его вернуть.

3 голосов
/ 14 марта 2011

Строка

T t;

По умолчанию создает объекты, но объявляет неинициализированные встроенные типы.Нет синтаксиса для «конструирования по умолчанию» локальной переменной.

Поэтому нетривиально написать универсальный код, который инициализирует переменную, встроенную или классную.

Заключение типа вОднако переменная-член может представлять собой обходной путь, который не требует создания копии (кроме оператора return):

template< typename T > struct Initializer {
   T t;
   Initializer()
   :t() // ====> default construction, works for classes _and_ built-in
   {}
};

Используя эту оболочку, вы можете создать свой код общим способом:

template<typename T> T foo() {
  Initializer<T> i;
  // fill in i.t to your liking
  return i.t;
}

См полномасштабный фрагмент на кодовая панель .

3 голосов
/ 14 марта 2011

Действительно, это стандартный способ решения проблемы.Я не верю, что в этом случае нужно беспокоиться о каких-либо побочных эффектах.

1 голос
/ 14 марта 2011

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

Почему бы вам не использовать подходящую обертку - если у вас есть доступ к boost, рассмотрите boost::optional.Таким образом, если вы не инициализируете его, его можно правильно протестировать.

1 голос
/ 14 марта 2011

Это похоже на примитивные типы (например, int и float) и классы, по крайней мере, пока этот класс имеет конструктор копирования

Для классов, не только [public] copy-constructor, вам также нужен public конструктор по умолчанию!

Мой вопрос - это приемлемый способ решения этой проблемы?

Обычно хорошей идеей является предоставление public конструктора по умолчанию. Контейнеры STL используют его постоянно! Если у вас нет одного, большинство (или, может быть, все) контейнеры STL не будут работать во многих случаях.

См. Этот пример с private конструктором по умолчанию: http://ideone.com/EdPLu

0 голосов
/ 06 марта 2013

Boost решает эту проблему в одном из классов шаблонов утилит, а именно boost :: value_initialized и его родственников.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...