2016-07-21 4 views
1
에서 "이항 동안 감지 앨리어싱 (aliasing)"

나는 다음과 같은 코드가 있습니다은 아이겐

정적 무효 아이겐을 오류가 발생

template <typename T> 
using Arr = Array<T, Dynamic, 1>; 

template <typename T> 
using Arr2 = Array<T, Dynamic, Dynamic>; 

template <typename T> 
Arr2<typename T::Scalar> reshape (const ArrayBase<T> & A, const uint n, const uint m) { 
    return Map<const Arr2<typename T::Scalar>>(A.eval().data(), n, m); 
} 

Arr<double> v = Arr<double>::LinSpaced(16, 0, 15); 
auto w = reshape(v, 4, 4).transpose(); 
std::cout << w << std::endl; 

:: 내부 :: checkTransposeAliasing_impl는 :: 실행 (CONST는 &을 유도 , const OtherDerived &) [Derived = Eigen :: Array로; OtherDerived = Eigen :: Transpose>; 부울 MightHaveTransposeAliasing] = TRUE : 어설 `(check_transpose_aliasing_run_time_selector :: IsTransposed, OtherDerived> :: 실행 (extract_data (DST), 기타)!) & &는 "또는 우를 평가"앨리어싱 전위 동안, transposeInPlace()를 사용하여 발견 " .eval() " '을 (를) 사용하여 임시로 에 연결하지 못했습니다.

eval를 추가하는 것은 참으로 문제 해결

auto w = reshape(v, 4, 4).transpose().eval(); 

을 (그러나 << w.eval() <<은하지 않습니다대로 인쇄 라인을 추가).

나는이 문제를 해결할 다른 방법이 있는지 계속 확인하고 싶습니다.

답변

0

기본적으로 당신은 기존 개체의 발현/참조를 만들 수 있습니다 감사합니다. 객체가 범위를 벗어나면 표현식/참조는 유효하지 않거나 정의되지 않습니다.

auto w을 사용하면 Arr2 오브젝트의 표현식을 작성합니다.이 오브젝트의 수명은이 라인 다음에 끝나며 w이 유효하지 않게됩니다. 당신이 본 주장은이 상황을 확인하는 데 도움이됩니다. Map 개체를 개체의 행 return에 캐스팅 할 때이 임시 개체는 입력 벡터에서 임시 Arr2 개체로의 바람직하지 않은 데이터 복사본이 포함될 때 만들어집니다. 이는 the situations that you should not use auto 중 하나입니다. 하나 이상의 복사본을 수락하면 다음 코드가 작동합니다. 원래 코드에 .eval()을 추가하는 것과 같습니다.

#include <Eigen/Eigen> 
#include <iostream> 
using namespace Eigen; 

template<typename T> 
using Arr = Array<T, Dynamic, 1>; 
template<typename T> 
using Arr2 = Array<T, Dynamic, Dynamic>; 

template<typename T> 
Arr2<typename T::Scalar> reshape(const ArrayBase<T> & A, const uint n, 
           const uint m) { 
    return Map<const Arr2<typename T::Scalar>>(A.eval().data(), n, m); 
} 

int main() { 
    Arr<double> v = Arr<double>::LinSpaced(16, 0, 15); 
    Arr2<double> w = reshape(v, 4, 4).transpose(); 
    std::cout << w << std::endl; 
    return 0; 
} 

또는 Map<const Arr2<typename T::Scalar>>에 반환 형식을 변경하면 위에서 언급 한 두 복사본을 피하기 위해 더 나은 방법이고, 당신은 여전히 ​​표현으로 w을 유지하기 위해 auto를 사용할 수 있습니다. 다음 코드는 더 나은 작업 버전입니다. 한편


#include <Eigen/Eigen> 
#include <iostream> 
using namespace Eigen; 

template<typename T> 
using Arr = Array<T, Dynamic, 1>; 
template<typename T> 
using Arr2 = Array<T, Dynamic, Dynamic>; 

template<typename T> 
Map<const Arr2<typename T::Scalar>> reshape(const ArrayBase<T> & A, 
              const uint n, const uint m) { 
    return Map<const Arr2<typename T::Scalar>>(A.eval().data(), n, m); 
} 

int main() { 
    Arr<double> v = Arr<double>::LinSpaced(16, 0, 15); 
    auto w = reshape(v, 4, 4).transpose(); 
    std::cout << w << std::endl; 
    return 0; 
} 

, 나는 A.eval().data() 누구의 삶 함수 호출 후에 종료 임시 객체이기 때문에 A는, 표현입니다 때 reshape 여전히 잘못 생각합니다. 귀하의 reshape API는이 제한을 모르는 사람들을 혼란스럽게합니다.

Map 개체 자체가 의미 상으로 인접한 메모리 공간에서 일부 데이터를 다시 형성한다는 의미이므로 실제로 모양 변경 기능을 만드는 것은 불필요합니다. 다음 양식을 추천합니다. "reshape"라는 단어보다 약간 길며 임시 버퍼/데이터 복사본이 포함되어 있지 않으며 auto w은 여전히 ​​표현 개체입니다.

#include <Eigen/Eigen> 
#include <iostream> 
using namespace Eigen; 

template<typename T> 
using Arr = Array<T, Dynamic, 1>; 
template<typename T> 
using Arr2 = Array<T, Dynamic, Dynamic>; 

int main() { 
    Arr<double> v = Arr<double>::LinSpaced(16, 0, 15); 
    auto w = Map<Arr2<double>>(v.data(), 4, 4).transpose(); 
    std::cout << w << std::endl; 
    return 0; 
} 
+0

어떻게 표현식을 "다시 형성 하시겠습니까?" –

+1

'Array' 객체에'eval()'을하고,'Map'을 호출합니다. – kangshiyin