在尝试将基于for循环的范围内的const引用值传递给a时出现问题 采用const引用值的函数。查看基于循环的范围内的通知,看看我在谈论什么。我的实施' unordered_vector'似乎不是一个问题。这是我最初的想法,因为它在函数外正确打印。为什么这会失败?如果我通过价值,它就有效,所以我在这里有点困惑。看起来它引用的引用似乎不是正确的行为。
void println(const vec3& p)
{
std::cout << '<' << p.x << ',' << p.y << ',' << p.z << '>' << std::endl;
}
void printlnvalue(vec3 p)
{
std::cout << '<' << p.x << ',' << p.y << ',' << p.z << '>' << std::endl;
}
const int vector_length = 7;
int _tmain(int argc, _TCHAR* argv[])
{
unordered_vector<vec3> vectors(vector_length);
for (int i = 0; i < vector_length; ++i)
{
vectors.push_back(vec3(0.1f*i, 0.2f*i, 0.3f*i));
}
for (const auto& i : vectors)
{
//Prints correctly
printlnvalue(i);
//Function that does same thing but doesn't print correctly.
println(i);
}
return 0;
}
输出
<0,0,0> <8.68805E-044,2.66467E-038,4.12969E-039> <0.1,0.2,0.3> <8.68805E-044,2.66467E-038,4.12969E-039> <0.2,0.4,0.6> <8.68805E-044,2.66467E-038,4.12969E-039> <0.3,0.6,0.9> <8.68805E-044,2.66467E-038,4.12969E-039> <0.4,0.8,1.2> <8.68805E-044,2.66467E-038,4.12969E-039> <0.5,1,1.5> <8.68805E-044,2.66467E-038,4.12969E-039> <0.6,1.2,1.8> <8.68805E-044,2.66467E-038,4.12969E-039>
unordered_vector声明
template<typename T>
class unordered_vector
{
private:
T* m_data;
size_t m_size;
size_t m_capacity;
public:
typedef unordered_vector_iterator<T> iterator;
typedef unordered_vector_iterator<T> const const_iterator;
typedef ptrdiff_t difference_type;
typedef size_t size_type;
typedef T value_type;
typedef T* pointer;
typedef T& reference;
size_t size(void) const;
size_t capacity(void) const;
bool empty(void) const;
void resize(size_t count);
void reserve(size_t count);
void push_back(const T& val);
const_iterator begin(void) const;
const_iterator end(void) const;
void shrink_to_fit(void);
void erase(size_t i);
void erase(const T& val);
void erase_all(const T& val);
T& operator[](size_t i);
T operator[](size_t i) const;
unordered_vector& operator=(const unordered_vector& copy);
unordered_vector& operator=(unordered_vector&& mov);
unordered_vector(void);
unordered_vector(size_t _size);
unordered_vector(unordered_vector& copy);
unordered_vector(unordered_vector&& mov);
~unordered_vector(void);
};
unordered_vector定义
template<typename T>
/*
Returns the number of active units within
the unordered_vector.
*/
size_t unordered_vector<T>::size(void) const
{
return m_size;
}
template<typename T>
/*
Returns the potential size of the vector
before it would have to resize.
*/
size_t unordered_vector<T>::capacity(void) const { return m_capacity; }
template<typename T>
/*
Returns true if no active units are within the vector. size() == 0
*/
bool unordered_vector<T>::empty(void) const
{
return m_size == 0;
}
template<typename T>
/*
This resizes the vector where anything between the parameter and
size is part of the capacity.
*/
void unordered_vector<T>::reserve(size_t count)
{
if (count > m_capacity)
{
//Set capacity to new value
m_capacity = count;
//Make new array
T* new_ptr = static_cast<T*>(malloc(sizeof(T)*m_capacity));
//Copy preexisting data byte for byte
if (m_data != nullptr)
{
//Copy data from previous buffer to new buffer
memcpy(new_ptr, m_data, sizeof(T)*m_size);
//Delete previous buffer
free(m_data);
}
//Set pointer to the new array
m_data = new_ptr;
}
}
template<typename T>
/*
Will resize the vector but each of the units is
active if the buffer is increased. If the size
is reduced then items at the end are truncated.
*/
void unordered_vector<T>::resize(size_t count)
{
if (count > m_capacity)
{
//Set capacity to new value
m_capacity = count;
//Make new array
T* new_ptr = static_cast<T*>(malloc(sizeof(T)*m_capacity));
//Copy preexisting data byte for byte
if (m_data != nullptr)
{
//Copy data from previous buffer to new buffer
memcpy(new_ptr, m_data, sizeof(T)*m_size);
//Delete previous buffer
free(m_data);
}
//Set pointer to the new array
m_data = new_ptr;
//Make default values at each location
for (; m_size < count; ++m_size)
{
}
}
else if (count < m_capacity)
{
if (count < m_size) m_size = count;
//Set capacity to new value
m_capacity = count;
//Make new array
T* new_ptr = static_cast<T*>(malloc(sizeof(T)*m_capacity));
//Copy preexisting data byte for byte
if (m_data != nullptr)
{
//Copy data from previous buffer to new buffer
memcpy(new_ptr, m_data, sizeof(T)*m_size);
//Delete previous buffer
free(m_data);
}
//Set pointer to the new array
m_data = new_ptr;
}
}
template<typename T>
/*
Shrinks capacity so capacity() == size().
*/
void unordered_vector<T>::shrink_to_fit(void)
{
if (m_size != m_capacity && m_data != nullptr)
{
m_capacity = m_size;
//Make new array
T* new_ptr = static_cast<T*>(malloc(sizeof(T)*m_capacity));
//Copy preexisting data byte for byte
memcpy(new_ptr, m_data, sizeof(T)*m_size);
//Delete previous buffer
if (m_data != nullptr)
free(m_data);
//Set pointer to the new array
m_data = new_ptr;
}
}
template<typename T>
/*
Will copy a value into the next open space of the vector.
If there isn't room for an additional item it will resize
the vector to accomadate it.
*/
void unordered_vector<T>::push_back(const T& val)
{
//If we don't have any more room we need
//to resize the array
if (m_size == m_capacity)
{
m_capacity = m_capacity == 0 ? 8 : m_capacity * 2;
//Make new array
T* new_ptr = static_cast<T*>(malloc(sizeof(T)*m_capacity));
if (m_data != nullptr)
{
//Copy preexisting data byte for byte
memcpy(new_ptr, m_data, sizeof(T)*m_size);
//Delete previous buffer
free(m_data);
}
//Set pointer to the new array
m_data = new_ptr;
}
m_data[m_size++] = val;
}
template<typename T>
/*
Random accessor for writing to array.
*/
T& unordered_vector<T>::operator[](size_t i)
{
assert(i >= 0 && i < m_size);
return m_data[i];
}
template<typename T>
/*
Random accessor for reading from array.
*/
T unordered_vector<T>::operator[](size_t i) const
{
assert(i >= 0 && i < m_size);
return m_data[i];
}
template<typename T>
/*
Constant time erase. It reorders the vector
internally to allow this.
*/
void unordered_vector<T>::erase(size_t i)
{
assert(i >= 0 && i < m_size);
if (i == m_size - 1)
m_size -= 1;
else
{
m_data[i] = m_data[m_size - 1];
m_size -= 1;
}
}
template<typename T>
/*
Will remove the first value that matches
val if it exists. In the event no value is
found the request is ignored.
*/
void unordered_vector<T>::erase(const T& val)
{
for (size_t i = 0; i < m_size; ++i)
{
if (m_data[i] == val)
{
if (i == m_size - 1)
m_size -= 1;
else
{
m_data[i] = m_data[m_size - 1];
m_size -= 1;
}
break;
}
}
}
template<typename T>
/*
Will remove all values that match the parameter.
If no items match the parameter then the request
is ignored.
*/
void unordered_vector<T>::erase_all(const T& val)
{
for (size_t i = 0; i < m_size; ++i)
{
if (m_data[i] == val)
{
if (i == m_size - 1)
m_size -= 1;
else
{
m_data[i] = m_data[m_size - 1];
m_size -= 1;
//Haven't checked the back yet
//so we need to recheck i
i--;
}
}
}
}
template<typename T>
/*
Initializes the vector with 0 capacity.
*/
unordered_vector<T>::unordered_vector(void)
: m_data(nullptr), m_size(0), m_capacity(0) {}
template<typename T>
/*
Initializes the vector with a capacity() equal to
the parameter.
*/
unordered_vector<T>::unordered_vector(size_t count)
: m_data(nullptr), m_size(0), m_capacity(0)
{
reserve(count);
}
template<typename T>
/*
Will copy data from another unordered_vector.
*/
unordered_vector<T>::unordered_vector(unordered_vector<T>& vector)
{
if (vector.m_capacity > 0)
{
m_data = malloc(sizeof(T)*vector.m_capacity);
if (vector.m_size > 0)
memcpy(m_data, vector.m_data, sizeof(T)*vector.m_size);
}
m_capacity = vector.m_capacity;
m_size = vector.m_size;
}
template<typename T>
/*
Move constructor to effeciently transfer data between
a temporary and another unordered_vector.
*/
unordered_vector<T>::unordered_vector(unordered_vector<T>&& mov)
{
m_data = mov.m_data;
m_capacity = mov.m_capacity;
m_size = mov.m_size;
mov.m_data = nullptr;
}
template<typename T>
/*
Destructor that deallocates memory
if any was allocated. Will not deallocate
memory if move semantic was invoked.
*/
unordered_vector<T>::~unordered_vector(void)
{
if (m_data != nullptr)
{
free(m_data);
m_data = nullptr;
}
m_size = 0;
m_capacity = 0;
}
template<typename T>
unordered_vector<T>& unordered_vector<T>::operator=(const unordered_vector<T>& copy)
{
if (m_data != nullptr)
{
free(m_data);
m_data = nullptr;
}
if (copy.m_capacity > 0)
{
m_data = malloc(sizeof(T)*copy.capacity());
if (copy.m_size > 0)
memcpy(m_data, copy.m_data, sizeof(T)*copy.m_size)
}
m_capacity = copy.m_capacity;
m_size = copy.m_size;
return *this;
}
template<typename T>
unordered_vector<T>& unordered_vector<T>::operator=(unordered_vector<T>&& mov)
{
if (m_data != nullptr)
free(m_data);
m_data = mov.m_data;
m_capacity = mov.m_capacity;
m_size = mov.m_size;
mov.m_data = nullptr;
}
template<typename T>
unordered_vector_iterator<T> const unordered_vector<T>::begin(void) const
{
return unordered_vector_iterator<T>(this, 0);
}
template<typename T>
unordered_vector_iterator<T> const unordered_vector<T>::end(void) const
{
return unordered_vector_iterator<T>(this, m_size);
}
迭代器声明
template<typename T>
class unordered_vector_iterator
{
private:
const unordered_vector<T>* const m_container;
size_t m_index;
public:
unordered_vector_iterator& operator++(void);
unordered_vector_iterator& operator++(int);
unordered_vector_iterator& operator--(void);
unordered_vector_iterator& operator--(int);
T& operator*(void) const;
T& operator->(void) const;
bool operator==(const unordered_vector_iterator& iter) const;
bool operator!=(const unordered_vector_iterator& iter) const;
unordered_vector_iterator(const unordered_vector<T>* const container, size_t index)
: m_container(container), m_index(index) {}
};
迭代器定义
template<typename T>
bool unordered_vector_iterator<T>::operator==(const unordered_vector_iterator<T>& iter) const
{
return iter.m_index == m_index && iter.m_container == m_container;
}
template<typename T>
bool unordered_vector_iterator<T>::operator!=(const unordered_vector_iterator<T>& iter) const
{
return iter.m_index != m_index || iter.m_container != m_container;
}
template<typename T>
unordered_vector_iterator<T>& unordered_vector_iterator<T>::operator++(void)
{
++m_index;
return *this;
}
template<typename T>
unordered_vector_iterator<T>& unordered_vector_iterator<T>::operator++(int)
{
++m_index;
return *this;
}
template<typename T>
unordered_vector_iterator<T>& unordered_vector_iterator<T>::operator--(void)
{
--m_index;
return *this;
}
template<typename T>
unordered_vector_iterator<T>& unordered_vector_iterator<T>::operator--(int)
{
--m_index;
return *this;
}
template<typename T>
T& unordered_vector_iterator<T>::operator*(void) const
{
return (*m_container)[m_index];
}
template<typename T>
T& unordered_vector_iterator<T>::operator->(void) const
{
return (*m_container)[m_index];
}
vec3声明
struct vec3
{
public:
float x, y, z;
//vector functions
void normalize(void);
float magnitude(void) const;
float magnitudeSq(void) const;
bool operator==(vec3 o) const;
bool operator!=(vec3 o) const;
//Constructors
vec3(float _x, float _y, float _z)
: x(_x), y(_y), z(_z) {}
vec3(float s)
: x(s), y(s), z(s) {}
vec3()
: x(0.f), y(0.f), z(0.f) {}
};
答案 0 :(得分:0)
您可能需要在unordered_vector
中声明另一个运算符才能返回const T&
。这就是它在STL vector
类中声明的方式:
typedef const_reference const T&;
const_reference operator[](size_t idx) const;
答案 1 :(得分:0)
代码的问题是const方法不返回引用值。
此外,为了使代码工作,由于某种原因,它必须返回非常量引用值。这不是一个很好的答案,但现在通过将const索引运算符更改为此可以完美地运行。
template<typename T>
/*
Random accessor for reading from array.
*/
T& unordered_vector<T>::operator[](size_t i) const
{
assert(i >= 0 && i < m_size);
return m_data[i];
}