我要提前为巨大的代码块道歉 - 我尽力将其归结为一个测试用例。
我的程序在标有注释的行上的vectorTest.cpp
中抛出了一个段错误。正如那里的评论所示,我已经跟踪了段{f}中的段错误。
问题似乎是我无法访问Matrix.h::Matrix< T >::operator[]
。这很奇怪,因为从O.rref()::rrefMatrix._values
的其余部分可以看到,访问vectorTest.cpp
,M._values
或M.rref()::rrefMatrix._values
时没有问题。只有当我使用O._values
后面的<{1>}函数 append()
时才会遇到我的错误。
我只是在绳子尽头。有人可以请我解释一下吗?
vectorTest.cpp:
Matrix< T >::rref()
Matrix.h:
#include "Vector.h"
#include "Polynomial.h"
#include "Matrix.h"
#include <iostream>
using namespace std;
int main( int argc, char* argv[] )
{
Matrix< float > M( 3, 3 );
M.setValues( { 1, 2, 3, 4, 5, 6, 7, 8, 8 } );
cout << M << endl;
cout << M.rref() << endl;
Matrix< float > N( 3, 1 );
N.setValues( { 2, -2, 5 } );
Matrix< float > O = append( M, N );
cout << O << endl;
cout << O.rref() << endl; //Segfault!
return 0;
}
Vector.h:
#ifndef __INCL_MATRIX_H__
#define __INCL_MATRIX_H__
#include "Vector.h"
#include <iterator>
#include <algorithm>
#include <utility>
#include <initializer_list>
#include <type_traits>
#include <iomanip>
#include <sstream>
#include <cassert>
template < class T >
class Matrix
: Vector< T >
{
public:
Matrix() :
Vector< T >::Vector()
{};
Matrix( const Matrix< T >& cMatrix ) :
Vector< T >::Vector( cMatrix ),
_numRows( cMatrix._numRows ),
_numColumns( cMatrix._numColumns )
{};
Matrix( const unsigned int r, const unsigned int c ) :
_numRows( r ),
_numColumns( c )
{
_values.reserve( r * c );
for( unsigned int r = 0; r < _numRows; r++ )
for( unsigned int c = 0; c < _numColumns; c++ )
_values[ r * _numColumns + c ] = T( 0 );
}
Matrix< T >& operator= ( const Matrix< T >& );
template < class InputIterator >
typename std::enable_if< std::is_same< T, typename std::iterator_traits< InputIterator >::value_type >::value, void >::type
setValues( InputIterator, InputIterator );
void setValues( std::initializer_list< T > );
T* operator[] ( const unsigned int );
const T* operator[] ( const unsigned int ) const;
unsigned int numRows() const;
unsigned int numColumns() const;
Matrix< T > rref() const;
protected:
void swapRows( const unsigned int, const unsigned int );
private:
using Vector< T >::_values;
unsigned int _numRows;
unsigned int _numColumns;
};
template < class T >
Matrix< T >& Matrix< T >::operator= ( const Matrix< T >& cMatrix )
{
_numRows = cMatrix._numRows;
_numColumns = cMatrix._numColumns;
_values = cMatrix._values;
return *this;
}
template < class T >
template < class InputIterator >
typename std::enable_if< std::is_same< T, typename std::iterator_traits< InputIterator >::value_type >::value, void >::type Matrix< T >::setValues( InputIterator begin, InputIterator end )
{
_values.clear();
for( auto it = begin; it != end; it++ )
if( _values.size() < _numRows * _numColumns )
_values.push_back( *it );
}
template < class T >
void Matrix< T >::setValues( std::initializer_list< T > iList )
{
setValues( iList.begin(), iList.end() );
}
template < class T >
T* Matrix< T >::operator[] ( const unsigned int r )
{
return &( _values[ r * _numColumns ] ); //This is the thorn in my paw.
}
template < class T >
const T* Matrix< T >::operator[] ( const unsigned int r ) const
{
return &( _values[ r * _numColumns ] );
}
template < class T >
unsigned int Matrix< T >::numRows() const
{
return _numRows;
}
template < class T >
unsigned int Matrix< T >::numColumns() const
{
return _numColumns;
}
template < class T >
constexpr T abs( const T a )
{
return ( a < 0 ) ? -a : a;
}
template < class T >
constexpr T gcd( const T a, const T b )
{
return ( a == b || b == 0 ) ? a : ( ( a < b ) ? gcd( abs( b ), abs( a ) ) : gcd( abs( a ) - abs( b ), abs( b ) ) );
}
template < typename T, typename... Ts >
constexpr T gcd( const T a, const T b, const Ts... others )
{
return gcd( gcd( a, b ), others... );
}
template < class T >
Matrix< T > Matrix< T >::rref() const
{
Matrix< T > rrefMatrix = (*this);
unsigned int p = rrefMatrix._numColumns;
T mult = 0, mult1 = 0, mult2 = 0;
for( unsigned int r1 = 0; r1 < rrefMatrix._numRows; r1++ )
{
p = rrefMatrix._numColumns;
for( unsigned int r2 = r1; r2 < rrefMatrix._numRows; r2++ )
{
for( unsigned int c = 0; c < rrefMatrix._numColumns; c++ )
{
if( rrefMatrix[r2][c] != T( 0 ) ) // Why is this segfaulting?
{
p = c;
break;
}
}
if( p != rrefMatrix._numColumns )
{
if( r2 > r1 )
{
rrefMatrix.swapRows( r1, r2 );
}
break;
}
}
if( p == rrefMatrix._numColumns )
break;
for( unsigned int r2 = 0; r2 < rrefMatrix._numRows; r2++ )
{
if( r1 == r2 ) continue;
mult = gcd( rrefMatrix[r1][p], rrefMatrix[r2][p] );
mult1 = mult * rrefMatrix[r2][p];
mult2 = mult * rrefMatrix[r1][p];
for( unsigned int c = 0; c < rrefMatrix._numColumns; c++ )
{
rrefMatrix[r1][c] *= mult1;
rrefMatrix[r2][c] *= mult2;
}
for( unsigned int c = 0; c < rrefMatrix._numColumns; c++ )
{
rrefMatrix[r2][c] -= rrefMatrix[r1][c];
rrefMatrix[r1][c] /= mult1;
}
}
}
for( unsigned int r = 0; r < rrefMatrix._numRows; r++ )
{
p = _numColumns;
for( unsigned int c = 0; c < rrefMatrix._numColumns; c++ )
{
if( rrefMatrix[r][c] != 0 )
{
p = c;
break;
}
}
if( p == rrefMatrix._numColumns ) continue;
mult = rrefMatrix[r][p];
for( unsigned int c = 0; c < rrefMatrix._numColumns; c++ )
rrefMatrix[r][c] /= mult;
}
return rrefMatrix;
}
template < class T >
void Matrix< T >::swapRows( const unsigned int r1, const unsigned int r2 )
{
for( unsigned int c = 0; c < _numColumns; c++ )
std::swap( (*this)[r1][c], (*this)[r2][c] );
}
template < class T >
unsigned int strLength( T& item )
{
std::stringstream ss;
ss << item;
return ss.str().length();
}
template < class T >
std::ostream& operator<< ( std::ostream& out, const Matrix< T >& cMatrix )
{
unsigned int maxLength = 0, currLength = 0;
for( unsigned int r = 0; r < cMatrix.numRows(); r++ )
for( unsigned int c = 0; c < cMatrix.numColumns(); c++ )
{
currLength = strLength( cMatrix[r][c] );
if( currLength > maxLength )
maxLength = currLength;
}
for( unsigned int r = 0; r < cMatrix.numRows(); r++ )
{
for( unsigned int c = 0; c < cMatrix.numColumns(); c++ )
out << std::setw( maxLength ) << cMatrix[r][c] << ' ';
out << std::endl;
}
return out;
}
template < class T >
Matrix< T > append( const Matrix< T >& lhs, const Matrix< T >& rhs )
{
Matrix< T > appendMatrix( lhs.numRows(), lhs.numColumns() + rhs.numColumns() );
for( unsigned int r = 0; r < appendMatrix.numRows(); r++ )
{
for( unsigned int c = 0; c < lhs.numColumns(); c++ )
{
appendMatrix[r][c] = lhs[r][c];
}
for( unsigned int c = 0; c < rhs.numColumns(); c++ )
{
appendMatrix[r][ c + lhs.numColumns() ] = rhs[r][c];
}
}
return appendMatrix;
}
#endif
输出:
#ifndef __INCL_VECTOR_H__
#define __INCL_VECTOR_H__
#include <vector>
#include <iostream>
#include <iterator>
#include <initializer_list>
#include <type_traits>
#include <assert.h>
struct VectorBase {};
template < class T >
class Vector
: public VectorBase
{
public:
Vector()
{};
Vector( const Vector< T >& cVector ) :
_values( cVector._values )
{};
template < class InputIterator >
Vector( InputIterator first, InputIterator last ) :
_values( first, last )
{};
Vector( std::initializer_list< T > iList ) :
_values( iList.begin(), iList.end() )
{};
protected:
std::vector< T > _values;
};
#endif
答案 0 :(得分:2)
在这个构造函数中:
Matrix( const unsigned int r, const unsigned int c ) :
_numRows( r ),
_numColumns( c )
{
_values.reserve( r * c );
for( unsigned int r = 0; r < _numRows; r++ )
for( unsigned int c = 0; c < _numColumns; c++ )
_values[ r * _numColumns + c ] = T( 0 );
}
改变这个:
_values.reserve( r * c );
对此:
_values.resize( r * c );
请参阅std::vector<>::reserve()的文档了解原因。它设定了容量;不是大小。这意味着您可以将向量增长到指定的容量,而不会触发内部重新分配以及可能被复制的对象。
注意:我会认真考虑使用基于r
和c
的预定大小的构建向量的重组。