23065


＜実行環境＞  
\- OS: OSX 10.11.3  
\- コンパイラ: clang++  
以下は、clang++ -vの出力  
Apple LLVM version 7.0.2 (clang-700.1.81)  
Target: x86_64-apple-darwin15.3.0  
Thread model: posix  
\-
非標準ライブラリとして、Eigenを使用（<http://eigen.tuxfamily.org/index.php?title=Main_Page>）  
\- C++11の機能を使用  
＜コード＞

[code]

    #include <iostream>   
    #include <Eigen/Core>
    
    using namespace std;
    using namespace Eigen;
    
    class A{
    private:
        VectorXd ma;
    public:
        A(VectorXd a = VectorXd::Ones(1)){
            ma = a;
        }
    
        VectorXd geta(){
            return ma;
        }
    };
    
    class B : public A{
    public:
       B(VectorXd a = VectorXd::Ones(1)): A(a){
           // In the following line, if you use the type name "VectorXd" and don't use "auto", you can get the normal result. 
           const auto b = 2 * geta();
    
           // If you release the comment out the following line, even if using the "auto" during initialization of b, you can get the normal result. 
           // const auto c = geta();
    
           cout << "b = " << b << endl;
           cout << "b = " << b << endl;
       }
    };
    
    int main() {
        VectorXd la = 2 * VectorXd::Ones(1);
        cout << "la = " << la << endl;
        B test = B();
    
        return 0;
    }
    
[/code]

＜実行結果＞

  1. 上記のコードをそのまま実行した場合の出力  
la = 2  
b = 2  
b = 4

  2. Class Bのコンストラクタ内の変数bの宣言・初期化時に型推論（auto）を使わずに、VectorXdという型を用いた場合の出力  
la = 2  
b = 2  
b = 2

  3. 変数bの宣言・初期化時には型推論を使用するが、その次の行でconst auto c = geta()という式を評価する場合の出力  
la = 2  
b = 2  
b = 2

＜質問内容＞  
修正を行う前のコードだと、意図していた動作（la及びbの２度の出力結果が同じ値を示す）にならない理由を伺いたです。bに型情報を与えることが解決策になることは、確かめることができましたが、なぜこのような動作になるのかが、未熟な私には理解できません。  
ご教示いただけると幸いです。


CC BY-SA 3.0
2016-03-10T14:49:29.390
22994
2016-03-12T14:31:43.973
14734
question
c++ c++11
Eigen::VectorXdを戻り値とする関数の出力を受け取る変数の宣言に、型推論を用いた時の挙動についての疑問


Eigenにはあまり詳しくないので，かなり推量が入っていますがご了承ください．

こちらの環境（VS2015）では，型推定を用いた場合のbの型は，

[code]

    class Eigen::CwiseUnaryOp<struct Eigen::internal::scalar_multiple_op<double>,class Eigen::Matrix<double,-1,1,0,-1,1> const>
    
[/code]

となっています．つまり，double と VectorXd の演算の式自体を表していることになります．  
この`b`を出力した場合，どうやら`b`の式を評価した結果が出力されるようです．  
したがって，`b`は出力するたびに評価され，

> la = 2  
>  b = 2  
>  b = 4

という結果になります．この後`b`を出力し続ければ，b = 8, b = 16 と
2倍になっていきます．`b`という式自体が計算を行う対象となるベクトルが何になるのかは，Eigenの仕組みによります．ただ，この場合に関しては，`b`を評価した結果得られたベクトルが，次の評価のベクトルとして使われているため，値が2倍に変化していき，もし，`const
auto c =
geta()`という式をはさんだ場合には（この`c`の型はVectorXdになる），評価には`c`の値が使われるようになり，結果として正しくなるようにみえます．ただし，これは偶然だと言ってよいでしょう．


CC BY-SA 3.0
2016-03-11T01:54:10.187
23008
2016-03-11T01:54:10.187
14575
22994
answer


Eigenライブラリでは「式テンプレート(ET; Expression
Template)」とよばれる[テクニックを利用](http://eigen.tuxfamily.org/dox/TopicLazyEvaluation.html)しているのですが、この技法は`auto`による変数型推論との相性がよくありません。

[混ぜるな危険! Eigenとauto](http://qiita.com/sakisakira/items/7c6952e59e958cefe7fa)
に詳しい説明がありましたのでそちらに譲ります。


CC BY-SA 3.0
2016-03-12T14:31:43.973
23065
2016-03-12T14:31:43.973
49
22994
answer