aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/vector20
-rw-r--r--tests/test_vector.cpp35
2 files changed, 45 insertions, 10 deletions
diff --git a/include/vector b/include/vector
index b5f363a..a068bc3 100644
--- a/include/vector
+++ b/include/vector
@@ -205,7 +205,8 @@ bool vector<_T>::reserve(size_type new_size)
if (is_pod<value_type>::value)
{
pointer oldBegin = mBegin;
- mBegin = static_cast<pointer>(realloc(mBegin, new_size * sizeof(value_type)));
+ mBegin = static_cast<pointer>(
+ realloc(mBegin, new_size * sizeof(value_type)));
if (!mBegin)
{
mBegin = oldBegin;
@@ -214,11 +215,14 @@ bool vector<_T>::reserve(size_type new_size)
}
else
{
- pointer newBegin = static_cast<pointer>(malloc(new_size * sizeof(value_type)));
+ pointer newBegin = static_cast<pointer>(
+ malloc(new_size * sizeof(value_type)));
if (!newBegin) return false;
- std::uninitialized_copy(mBegin, mBegin + mLength, newBegin);
- if (mBegin) deallocate();
+ if (mBegin != NULL) {
+ std::uninitialized_copy(mBegin, mBegin + mLength, newBegin);
+ deallocate();
+ }
mBegin = newBegin;
}
mCapacity = new_size;
@@ -235,7 +239,13 @@ void vector<_T>::push_back(const value_type& elt)
if (0 == new_capacity || !reserve(new_capacity)) return;
}
// mLength < mCapacity
- *(mBegin + mLength) = elt;
+ if (is_pod<value_type>::value) {
+ *(mBegin + mLength) = elt;
+ } else {
+ // The memory where the new element is added is uninitialized,
+ // we cannot use assigment (lhs is not valid).
+ new((void *)(mBegin + mLength)) _T(elt);
+ }
++mLength;
}
diff --git a/tests/test_vector.cpp b/tests/test_vector.cpp
index 2412607..cf3b7c7 100644
--- a/tests/test_vector.cpp
+++ b/tests/test_vector.cpp
@@ -32,9 +32,11 @@
#endif
#include <climits>
#include <cstring>
+#include <string>
#include "common.h"
namespace android {
+using std::string;
using std::vector;
static const size_t kExponentialFactor = 2;
bool testConstructorInt()
@@ -68,6 +70,17 @@ bool testConstructorInt()
return true;
}
+bool testConstructorString()
+{
+ {
+ vector<string> vec1;
+ EXPECT_TRUE(vec1.empty());
+ EXPECT_TRUE(vec1.size() == 0);
+ EXPECT_TRUE(vec1.capacity() == 0);
+ }
+ return true;
+}
+
typedef enum { ONE = 10, TWO} TestEnum;
template<typename T> struct A { };
@@ -163,7 +176,7 @@ bool testReserve()
c.mCount = 0;
vector<CopyCounter> vec4(100, c);
EXPECT_TRUE(c.mCount == 100);
- // Resizing does not do any copy via the copy assignement op.
+ // Growing does not do any copy via the copy assignement op.
vec4.reserve(1000);
EXPECT_TRUE(c.mCount == 200);
vec4.reserve(50); // reserving less than length is a nop.
@@ -192,10 +205,11 @@ bool testPushBack()
}
EXPECT_TRUE(vec1.capacity() == 1024);
EXPECT_TRUE(vec1.size() == 1000);
- EXPECT_TRUE(c.mAssignCount == 1000);
- // Due to the multiple augmentation of the capacity, the copy
- // constructor has been invoked.
- EXPECT_TRUE(c.mCopyCtorCount > 0);
+ // Assignment should not be used, but the constructor should.
+ EXPECT_TRUE(c.mAssignCount == 0);
+ // Copy constructor was been invoked for each new element
+ // pushed and when the capacity was increased.
+ EXPECT_TRUE(c.mCopyCtorCount > 1000);
EXPECT_TRUE(c.mCtorCount == 0);
}
{
@@ -210,6 +224,16 @@ bool testPushBack()
EXPECT_TRUE(vec2.back() == 20);
EXPECT_TRUE(vec2.size() == 2);
}
+ // Push back an non-pod object.
+ {
+ string str = "a string";
+ vector<string> vec3;
+
+ vec3.push_back(str);
+ EXPECT_TRUE(vec3.size() == 1);
+ EXPECT_TRUE(vec3.front() == "a string");
+ EXPECT_TRUE(vec3.back() == "a string");
+ }
return true;
}
@@ -362,6 +386,7 @@ bool testCtorDtorForNonPod()
int main(int argc, char **argv)
{
FAIL_UNLESS(testConstructorInt);
+ FAIL_UNLESS(testConstructorString);
FAIL_UNLESS(testConstructorRepeat);
FAIL_UNLESS(testReserve);
FAIL_UNLESS(testPushBack);