2016-02-18 4 views
4

Есть ли способ построить vector как конкатенации 2 vector сСтроительство вектор из конкатенации 2 векторов

Например (кроме создания вспомогательной функции?):

const vector<int> first = {13}; 
const vector<int> second = {42}; 
const vector<int> concatenation = first + second; 

Я знаю, что vectorне есть оператор добавления, такой как string, но это поведение, которое я хочу. Такой, что concatenation будет содержать: 13 и 42.

Я знаю, что я могу инициализировать concatenation, как это, но это мешает мне сделать concatenationconst:

vector<int> concatenation = first; 
first.insert(concatenation.end(), second.cbegin(), second.cend()); 
+0

буквально первый результат Google http://stackoverflow.com/questions/201718/concatenating-two-stdvectors – RyanP

+0

@RyanP Пропустил ли я что-то там, которое отвечало на мой вопрос? Или, может быть, я должен предположить, что ответ на мой вопрос - нет, так как там ничего не было, на что он ответил? –

+0

Если вы не можете использовать методы, которые изменяют контейнер, и вы не хотите использовать вспомогательный метод и нет оператора сложения для вектора, то я боюсь, что ответ на ваш вопрос - нет. –

ответ

5

Нет, это не возможно, если требуется, чтобы

  • нет помощника функция определена, и
  • результирующий вектор может быть объявлен const.
+4

Я немного опечален, увидев, что из всех ответов, которые я дал, именно этот минус дал мне мой золотой значок C++. : o [ –

+0

Я чувствую, что там есть жизненный урок ... – RyanP

+0

@Reader Я принимаю это, но есть хак, который может обойти эту проблему здесь: http://stackoverflow.com/a/35555016/2642059 –

0

Я думаю, что вы должны написать функцию помощи. Я бы написать:

std::vector<int> concatenate(const std::vector<int>& lhs, const std::vector<int>& rhs) 
{ 
    auto result = lhs; 
    std::copy(rhs.begin(), rhs.end(), std::back_inserter(result)); 
    return result; 
} 

ВЫЗОВ МАСТЕРА как:

const auto concatenation = concatenate(first, second); 

Если векторы, вероятно, будут очень велики (или содержат элементы, которые являются дорогостоящими для копирования), то вам, возможно, потребуется чтобы сделать reserve первым, чтобы сохранить перераспределения:

std::vector<int> concatenate(const std::vector<int>& lhs, const std::vector<int>& rhs) 
{ 
    std::vector<int> result; 
    result.reserve(lhs.size() + rhs.size()); 
    std::copy(lhs.begin(), lhs.end(), std::back_inserter(result)); 
    std::copy(rhs.begin(), rhs.end(), std::back_inserter(result)); 
    return result; 
} 

(Лично я бы только беспокоить, если есть доказательства того, что это узкое место).

+1

Вы можете сделать это с 0 перераспределением 'результата'. – LogicStuff

+1

ОП задает вопрос о том, как это сделать без вспомогательной функции (я тоже не видел этого изначально.) – juanchopanza

+0

@LogicStuff: Да, вы можете - но я полагаю, что это, вероятно, не стоит дополнительной сложности, если вы не знаете, что эта функция будет сильно используется. Перераспределение векторов действительно не так дорого. –

1
template<typename T> 
std::vector<T> operator+(const std::vector<T>& v1, const std::vector<T>& v2){ 
    std::vector<T> vr(std::begin(v1), std::end(v1)); 
    vr.insert(std::end(vr), std::begin(v2), std::end(v2)); 
    return vr; 
} 

Это действительно требует «функцию» помощника, но, по крайней мере, это позволяет использовать его в качестве

const vector<int> concatenation = first + second; 
+2

Не очень оптимальный, как и другой ответ. Это приведет к по меньшей мере одному перераспределению, которое может быть дорогостоящим. – NathanOliver

+0

@NathanOliver: «Это вызовет хотя бы одно перераспределение» - это зависит от вашей реализации. Если первый и второй меньше минимального размера вектора, то это не будет. –

+0

Optimal не требовал; требование заключалось в том, чтобы конкатенировать два вектора в const-вектор. Если избежать перераспределения, это требование, то перегрузка оператора может быть расширена для инициализации возвращаемого возвращаемого значения с резервным размером v1.size() + v2.size(). –

0
class Vector : public vector<int> 
{ 
public: 
    Vector operator+(const Vector& vec); 
}; 

Vector Vector::operator+(const Vector& vec) 
{ 
    for (int i = 0; i < vec.size(); i++) 
    { 
     this->push_back(vec[i]); 
    } 

    return *this; 
} 
+0

Это не только * * требует записи дополнительной функции, но также требует, чтобы я создал и использовал нестандартный класс, и он показывает гораздо более вирулентную версию проблемы перераспределения, чем ответ @MartinBonner: http://stackoverflow.com/questions/35485866/vector-construction-from-the-concatenation-of-2-vectors?noredirect=1#comment58665572_35486013 –

0

Позвольте мне предварить это, говоря, что это хак, и не дать ответ на то, как сделать это с помощью vector. Вместо этого мы будем зависеть от sizeof(int) == sizeof(char32_t) и использовать u32string, чтобы содержать наши данные.

This answer делает его чрезвычайно ясно, что только примитивы могут быть использованы в basic_string, и что любые примитивные больше, чем 32-бит потребует написания пользовательских char_traits, но для int мы можем просто использовать u32string.

Квалификационная для этого может быть подтверждено, выполнив:

static_assert(sizeof(int) == sizeof(char32_t)); 

После того размера равенство было установлено, и с осознанием того, что такие вещи, как не- constdata и emplace или emplace_back не могут быть использованы, u32string может можно использовать как vector<int>, с заметным включением капельной opperator:

const vector<int> first = {13}; 
const vector<int> second = {42}; 
const u32string concatenation = u32string(first.cbegin(), first.cend()) + u32string(second.cbegin(), second.cend()); 

[Live Example]

Смежные вопросы