C++编程调试秘笈----读书笔记(3)

三、索引越界

1、动态数组可以使用new,也可以用vector来动态创建

但是当下标的索引超过size的时候,new出来的数组对其进行更改的时候会有不确定的错误产生;vector提供了一个at(index)的函数,他通过抛出一个out_of_range异常执行边界检测

测试代码(vs2012+win7环境):

#include "stdafx.h"
#include "scpp_assert.h"
#include "iostream"
#include "vector"

#define SIZE 10

int _tmain(int argc, _TCHAR* argv[])
{
	char *str = new char[SIZE];
	str[SIZE + 1] = 'x';

	std::vector<char> arrayStr;
	arrayStr.resize(SIZE);
	arrayStr[11] = 'x';

	return 0;
}

他的问题在于如果我们想执行这种安全检查,必须在访问数组元素的每个地方都严格地使用at()函数。显然这种做法会降低代码的效率,因此在完成了测试之后,我们可能想要速度更快的[]操作符在每处对他继续拧替换。但是,这样的替换对代码进行大量的修改。因此可以使用下面的方法(以解决不必使用at函数):

#ifndef __SCPP_VECTOR_H__
#define __SCPP_VECTOR_H__

#include "scpp_assert.h"
#include "vector"

namespace scpp
{
	template <typename T>
	class vector : public std::vector<T>
	{
	public:
		typedef unsigned size_type;
	public:
		explicit vector(size_type n = 0)	: std::vector<T>(n){ }
		vector(size_type n, const T& value)	: std::vector<T>(n, value){ }

		template <class InputIterator> vector(InputIterator first, InputIterator last)
			: std::vector<T>(first, last){ }

		T &operator[] (size_type index)
		{
			SCPP_TEST_ASSERT(index < std::vector<T>::size(),
				"Index " << index << " must be less than "
				<< std::vector<T>::size());
			return std::vector<T>::operator [](index);
		}

		const T &operator[] (size_type index) const
		{
			SCPP_TEST_ASSERT(index < std::vector<T>::size(),
				"Index " << index << " must be less than "
				<< std::vector<T>::size());
			return std::vector<T>::operator [](index);
		}
	};
}; // namespace scpp

template <typename T>
inline std::ostream &operator << (std::ostream &os, const scpp::vector<T>& v)
{
	for (unsigned index = 0; index < v.size(); ++index)
	{
		os << v[index];
		if (index + 1 < v.size())
		{
			os << " ";
		}
	}
	return os;
}

#endif

测试代码(vs2012+win7环境):

#include "stdafx.h"
#include "scpp_assert.h"
#include "iostream"
#include "scpp_vector.h"

#define SIZE 10

int _tmain(int argc, _TCHAR* argv[])
{
	scpp::vector<char> str(SIZE, 'z');
	std::cout << str << std::endl;

	str[20] = 'x';

	return 0;
}

stdafx.h中打开调试开关:

#pragma once

#include "targetver.h"

#include <stdio.h>
#include <tchar.h>


// TODO: 在此处引用程序需要的其他头文件
/*#define SCPP_THROW_EXCEPTION_ON_BUG*/
#define SCPP_TEST_ASSERT_ON

2、静态数组:

scpp::vector vect(SIZE)他的效果与静态数组完全相同,但问题在于效率。静态数组是在堆栈上分配内存,而vector模板输在构造函数中使用new操作符分配的,速度比较慢,所以这里有array模板:

scpp_array.h:

#ifndef __SCPP_ARRAY_H__
#define __SCPP_ARRAY_H__

#include "scpp_assert.h"

namespace scpp
{
	template <typename T, unsigned N>
	class array
	{
	public:
		typedef unsigned size_type;

	public:
		array(){ }
		explicit array(const T& initialValue)
		{
			for (size_type index = 0; index < N; ++index)
			{
				data_[index] = initialValue;
			}
		}

		size_type size() const { return N; }

		T& operator[](size_type index)
		{
			SCPP_TEST_ASSERT(index < N,
				"Index " << index << " must be less than " << N);
			return data_[index];
		}
		const T& operator[](size_type index) const
		{
			SCPP_TEST_ASSERT(index < N,
				"Index " << index << " must be less than " << N);
			return data_[index];
		}

		T* begin() { return &data_[0]; }
		const T* begin() const { return &data_[0]; }

		T* end() { return &data_[N]; }
		const T* end() const { return &data_[N]; }
	private:
		T data_[N];
	};
}

template <typename T, unsigned N>
inline std::ostream &operator << (std::ostream &os, const scpp::array<T, N>& v)
{
	for (unsigned index = 0; index < v.size(); ++index)
	{
		os << v[index];
		if (index + 1 < v.size())
		{
			os << " ";
		}
	}
	return os;
}

#endif // __SCPP_ARRAY_H__

测试代码(vs2012+win7环境):

#include "stdafx.h"
#include "scpp_assert.h"
#include "iostream"
#include "scpp_vector.h"
#include "scpp_array.h"
#include "algorithm"

#define SIZE 10

int _tmain(int argc, _TCHAR* argv[])
{
	scpp::array<int, SIZE> str(1);
	str[0] = 7;
	str[1] = 2;
	str[2] = 8;
	str[3] = 4;

	std::cout << str << std::endl;
	std::sort(str.begin(), str.end());
	std::cout << str << std::endl;

	return 0;
}

这个数组的行为和C的静态数组完全一样。但是,在编译时激活了表示安全检查的SCPP_TEST_ASSERT_ON宏时,他会提供索引边界检查。提供了beginend方法,所以可以使用algorithm的一些算法


3、多维数组

其实多维数组也就是矩阵,如果矩阵的大小在编译时时已知的,可以很方便地把它实现为数组的数组。因此将注意力集中在当矩阵的大小是在运行时计算产生的这种情况。内部可以用一个vector来存储,返回的时候只需要加上index就行

scpp_matrix.h

#ifndef __SCCP_MATRIX_H__
#define __SCCP_MATRIX_H__

#include "ostream"
#include "vector"

#include "scpp_assert.h"

namespace scpp
{
	template <typename T>
	class matrix
	{
	public:
		typedef unsigned size_type;
	public:
		matrix(size_type numRows, size_type numCols)
			:rows_(numRows), cols_(numCols), data_(numCols * numRows)
		{
			SCPP_TEST_ASSERT(numRows > 0,
				"Number of rows in a matrix must be positive");
			SCPP_TEST_ASSERT(numCols > 0,
				"Number of cols in a matrix must be positive");
		}
		matrix(size_type numRows, size_type numCols, const T& initValue)
			:rows_(numRows), cols_(numCols), data_(numCols * numRows)
		{
			SCPP_TEST_ASSERT(numRows > 0,
				"Number of rows in a matrix must be positive");
			SCPP_TEST_ASSERT(numCols > 0,
				"Number of cols in a matrix must be positive");
		}

		size_type numRows() const { return rows_; }
		size_type numCols() const { return cols_; }

		T& operator() (size_type row, size_type col)
		{
			return data_[ index(row, col) ];
		}
		const T& operator() (size_type row, size_type col) const
		{
			return data_[ index(row, col) ];
		}
	private:
		size_type index(size_type row, size_type col) const
		{
			SCPP_TEST_ASSERT(row < rows_,
				"Row" << row << " must be less than " << rows_);
			SCPP_TEST_ASSERT(col < cols_,
				"Col" << col << " must be less than " << cols_);

			return cols_ * row + col;
		}
	private:
		size_type rows_;
		size_type cols_;
		vector<T> data_;
	};
}

template <typename T>
inline std::ostream &operator << (std::ostream &os, const scpp::matrix<T>& m)
{
	for (unsigned rowIndex = 0; rowIndex < m.numRows(); ++rowIndex)
	{
		for (unsigned colIndex = 0; colIndex < m.numCols(); ++colIndex)
		{
			os << m(rowIndex, colIndex);
			if (colIndex < m.numCols())
			{
				os << "\t";
			}
		}
	}
	return os;
}

#endif

测试代码(vs2012+win7环境):

#include "stdafx.h"
#include "scpp_assert.h"
#include "iostream"
#include "scpp_vector.h"
#include "scpp_array.h"
#include "scpp_matrix.h"
#include "algorithm"

#define SIZE 10

int _tmain(int argc, _TCHAR* argv[])
{
	scpp::matrix<int> scppMatrix(2, 2);
	scppMatrix(0, 0) = 1;
	scppMatrix(0, 1) = 2;
	scppMatrix(1, 0) = 3;
	scppMatrix(1, 1) = 4;
	scppMatrix(6, 6) = 4;

	std::cout << scppMatrix << std::endl;

	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值