1

我要提前为巨大的代码块道歉——我尽我所能把它归结为一个测试用例。

vectorTest.cpp我的程序在标有注释的行中抛出了一个段错误。Matrix.h::Matrix< T >::operator[]正如那里的评论所示,我已经将段错误一直追踪到 inside 。

问题似乎是我无法访问O.rref()::rrefMatrix._values. 这很奇怪,因为正如您从其他部分看到的那样,我访问、或vectorTest.cpp没有问题。只有当我使用后面的函数时,我才会遇到错误。M._valuesM.rref()::rrefMatrix._valuesO._valuesappend()Matrix< T >::rref()

我快走到尽头了。有人可以指出我的解释吗?

矢量测试.cpp:

#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;
}

矩阵.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

矢量.h:

#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

输出:

1 2 3 
4 5 6 
7 8 8 

 1 -0 -0 
-0  1 -0 
 0  0  1 

 1  2  3  2 
 4  5  6 -2 
 7  8  8  5 

Segmentation fault (core dumped)
4

1 回答 1

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

于 2013-04-21T07:13:00.867 回答