2014-11-24 2 views
1

Итак, я писал функцию, которая должна действовать как одна, возвращая массив (поскольку вы знаете, что массивы не могут быть возвращены на C++), и для этого мне нужно одно временное неназванное, которое должно использоваться как значение по умолчанию для параметра, присвоенное последний аргумент неявно, например:C++ как объявить временный неназванный, неинициализированный массив?

template<size_t szArr, typename typeArrs> 
auto fnAdd2ArrayElements(const typeArrs (&arr_0)[szArr], const typeArrs (&arr_1)[szArr], typeArrs (&&result)[szArr] = {}) -> typeArrs (&&)[szArr] 
{ 
    for(size_t i(0); i < szArr; ++i) 
     result[i] = arr_0[i] + arr_1[i]; 

    return move(result); 
} 

Как вы можете видеть, что параметр «результат» имеет значение параметра по умолчанию безымянного массива, который, однако будет всегда «нулями», из-за пустые скобки. Это снизит производительность, потому что, поскольку вы можете видеть, что моя функция не заботится о ее содержимом и заполнит все это. В любом случае я могу объявить его неинициализированным. Что-то вроде этого:

template<typename T, size_t sz> using identity = T [sz]; 

template<size_t szArr, typename typeArrs> 
auto fnAdd2ArrayElements(const typeArrs (&arr_0)[szArr], const typeArrs (&arr_1)[szArr], typeArrs (&&result)[szArr] = identity<typeArrs, szArr>()) -> typeArrs (&&)[szArr] 
{ 
    for(size_t i(0); i < szArr; ++i) 
     result[i] = arr_0[i] + arr_1[i]; 

    return move(result); 
} 

Но приведенный выше код не компилируется. Итак, любые идеи, как это можно сделать?

РЕДАКТОР: Кажется, возникают другие проблемы. Поскольку мы возвращаем «значение xvalue» (а не «prvalue»), если мы сохраняем результат в ссылке «rvalue», срок жизни неназванного временного не будет расширяться, как если бы мы вернули массив по значению , Вот пример:

const int iArr[] = {0, 1, 2, 3, 4}; 

const int iArr1[] = {0, 1, 2, 3, 4}; 

int (&&added)[5] = fnAdd2ArrayElements(iArr, iArr1); //this will create an dangling reference 

added[0]; //illegal - accessing dangling reference 
+1

Почему вы (думаю, вам) нужно возвращать массив? Как вы планируете использовать это? [И почему вы не используете вектор?] –

+6

Вы считали 'std :: array'? – Jarod42

+0

Да, но я хочу напрямую использовать встроенные массивы. – AnArrayOfFunctions

ответ

3

Было бы рискованно, так как срок службы этого временного является коротким:

template <typename T, size_t N> 
struct UninitializedArray 
{ 
    UninitializedArray() {} 
    T arr[N]; 
}; 

template <size_t szArr, typename typeArrs> 
typeArrs (&&)[szArr] 
fnAdd2ArrayElements(
    const typeArrs (&arr_0)[szArr], 
    const typeArrs (&arr_1)[szArr], 
    typeArrs (&&result)[szArr] = UninitializedArray<typeArrs, szArr>{}.arr) 
{ 
    std::cout << result[0] << std::endl; // To check that value is not initialized. 

    for (size_t i(0); i < szArr; ++i) { 
     result[i] = arr_0[i] + arr_1[i]; 
    } 
    return std::move(result); 
} 

Live example

+0

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

0

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

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

0

Проблема заключается в том, что прохождение указателей на функцию приводит к разложению аргументов функции указателям (даже если ваш код вызывает их ссылки, они являются указателями). Вы не можете вернуть указатель «в массив» - это будет означать, что компилятор должен будет сделать memcpy(dest, fnAdd2ArrayElements(...), number_of_bytes);, но он не знает фактическую длину number_of_bytes из кода.

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

void fnAdd2ArrayElements(const typeArrs (&arr_0)[szArr], 
         const typeArrs (&arr_1)[szArr], 
         typeArrs (&result)[szArr]); 

Вы, однако, должны инициализировать оригинальный result.

В качестве альтернативы, это мое предпочтительное решение: используйте std::vector [или аналогичные].

+0

Нет Если используется параметр по умолчанию - неназванный временной. – AnArrayOfFunctions

+0

Правильно, поэтому COMPILER заполнит аргумент, вам просто не нужно ТИП его. Это означает, что он создан и передан функции [очевидно, подвержен оптимизации, но вы используете «результат» в цикле, поэтому компилятор не может удалить конструкцию и разрушение, по крайней мере]. C и C++ никогда не были предназначены для того, чтобы делать то, что вы пытаетесь сделать, и я не вижу никакого способа, которым он будет работать. –

+0

Он делает - он компилируется отлично. И как вы думаете, что возвращаемые значения создаются, если не так, как аргументы? С ними нет ничего волшебного, память выделяется для них в стеке, так же как эта функция выделяет его для неназванной переменной. – AnArrayOfFunctions