admin管理员组

文章数量:1394217

The following does not produce an error when compiling:

std::vector<int> vectest = {};
unsigned int a = 3;
vectest.push_back(a);

This is valid as well:

std::vector<unsigned int> vectest = {};
int a = 3;
vectest.push_back(a);

While this does produce an error:

std::vector<std::vector<int>> matrtest = {};
std::vector<unsigned int> vectest2 = {1};
matrtest.push_back(vectest2);

Error:

error: no matching function for call to 'std::vectorstd::vector<int>::push_back(std::vector&)'

And this one as well:

std::vector<std::vector<unsigned int>> matrtest = {};
std::vector<int> vectest2 = {1};
matrtest.push_back(vectest2);

Error:

error: no matching function for call to 'std::vector<std::vector>::push_back(std::vector&)'

What is the logic behind this?

I'm using C++ 11

The following does not produce an error when compiling:

std::vector<int> vectest = {};
unsigned int a = 3;
vectest.push_back(a);

This is valid as well:

std::vector<unsigned int> vectest = {};
int a = 3;
vectest.push_back(a);

While this does produce an error:

std::vector<std::vector<int>> matrtest = {};
std::vector<unsigned int> vectest2 = {1};
matrtest.push_back(vectest2);

Error:

error: no matching function for call to 'std::vectorstd::vector<int>::push_back(std::vector&)'

And this one as well:

std::vector<std::vector<unsigned int>> matrtest = {};
std::vector<int> vectest2 = {1};
matrtest.push_back(vectest2);

Error:

error: no matching function for call to 'std::vector<std::vector>::push_back(std::vector&)'

What is the logic behind this?

I'm using C++ 11

Share Improve this question edited Mar 14 at 16:32 TylerH 21.1k79 gold badges79 silver badges114 bronze badges asked Mar 12 at 18:12 Julien Larget-PietJulien Larget-Piet 991 silver badge7 bronze badges 11
  • 2 int and unsigned int are implicitly convertible types, but a vectors of different types are not convertible even if the types they hold are convertible. – user4581301 Commented Mar 12 at 18:15
  • 2 Unrelated: vectors of vectors are painfully slow because of poor spatial locality. The outer vector holds a pointer to an array of vectors , and each vector in that array holds a pointer to an array of some type. All of these arrays could be scattered throughout memory, hindering the CPUs ability to make effective use of cache. Unless you need a jagged array, the rows of data can be different lengths, you're better off making something like what doug describes in this link. – user4581301 Commented Mar 12 at 18:24
  • 2 You could use vector::emplace_back and the vector constructor that takes iterators to do the conversion though example. – Ted Lyngmo Commented Mar 12 at 19:05
  • 1 @user4581301 A case of premature "optimization". For most use cases, a vector of vector is just fine, and much better maintainable than a custom data container with much reduced versatility. To quote Kate Gregory, "If you need a collection class, use vector. If you are special and performance matters to you and vector isn't going to work for you, no problem, I totally get it, use vector". Don't start down the road of custom data containers unless you have measured evidence that this is where an existing performance problem is located. – DevSolar Commented Mar 13 at 9:00
  • 1 vector<vector<...>> might be fine in certain cases. But I think @user4581301 does have a point when we need to represent numeric matrices. Many libraries (e.g. opencv - see cv::Mat) hold the actual data in a 1D vector (and not 2D) and supply access via 2 indices that are converted into the 1D one. This addresses the memory locality mentioned above. – wohlstad Commented Mar 13 at 13:08
 |  Show 6 more comments

1 Answer 1

Reset to default 10

An int can be converted to an unsigned int and vice-versa.

This is why you can push_back an int into a vector of unsigned int and vice-versa.

But std::vector<int> and std::vector<unsigned int> are completely unrelated types, and there is no out-of-the-box conversion between them.
(This is true for any two instatiations of the templated std::vector with different element types).

Therefore you can't push_back one into a vector of the other.

As @TedLyngmo commented, what you can do instead is use std::vector::emplace_back, together with std::vector constructor that accepts iterators:

std::vector<std::vector<int>> matrtest1 = {};
std::vector<unsigned int> vectest21 = {1};
matrtest1.emplace_back(vectest21.begin(), vectest21.end());

std::vector<std::vector<unsigned int>> matrtest2 = {};
std::vector<int> vectest22 = {1};
matrtest2.emplace_back(vectest22.begin(), vectest22.end());

Live demo

Note:
You mentioned you use C++11. Note that the above (regarding the unrelated types etc.) holds for newer versions of C++ as well (in case you'll considered to upgrade).

本文标签: