始める無料で始める

ベクトルのクローン

R と異なり、C++ は参照によるコピーの仕組みを使います。つまり、変数をコピーしてそのコピーに変更を加えると、元の変数にも同じ変更が反映されます。

// [[Rcpp::export]]
NumericVector always_returns_two(NumericVector x) {
  // コピーを作成
  NumericVector y = x;
  // コピーを変更
  y[0] = 2;
  // 変更は元のオブジェクトにも起こる
  return x[0];
}

この振る舞いを防ぐには、clone() 関数を使って、元の変数の基になるデータを新しい変数にコピーする必要があります。構文は y = clone(x) です。 この演習では、次の2つの関数を用意しています。

  • change_negatives_to_zero():数値ベクトルを受け取り、負の数をゼロに置き換えるように変更し、元のベクトルとコピーの両方を返します。
  • change_negatives_to_zero_with_cloning():上と同じ処理を行いますが、変更する前に元のベクトルをクローンします。

この演習はコースの一部です

Rcpp で R コードを最適化する

コースを見る

演習の手順

  • change_negatives_to_zero() の定義を完成させ、the_originalthe_copy に設定してください。
  • change_negatives_to_zero_with_cloning() の定義を完成させ、the_copythe_original のクローンに設定してください。
  • コンソールの出力を読んで、各関数の結果を比較してください。

実践的なインタラクティブ演習

このサンプルコードを完成させて、この演習に挑戦してみましょう。

#include 
using namespace Rcpp;

// [[Rcpp::export]]
List change_negatives_to_zero(NumericVector the_original) {
  // Set the copy to the original
  NumericVector the_copy = ___;
  int n = the_original.size();
  for(int i = 0; i < n; i++) {
    if(the_copy[i] < 0) the_copy[i] = 0;
  }
  return List::create(_["the_original"] = the_original, _["the_copy"] = the_copy);
}

// [[Rcpp::export]]
List change_negatives_to_zero_with_cloning(NumericVector the_original) {
  // Clone the original to make the copy
  NumericVector the_copy = ___;
  int n = the_original.size();
  for(int i = 0; i < n; i++) {
    if(the_copy[i] < 0) the_copy[i] = 0;
  }
  return List::create(_["the_original"] = the_original, _["the_copy"] = the_copy);
}

/*** R
x <- c(0, -4, 1, -2, 2, 4, -3, -1, 3)
change_negatives_to_zero(x)
# Need to define x again because it's changed now
x <- c(0, -4, 1, -2, 2, 4, -3, -1, 3)
change_negatives_to_zero_with_cloning(x)
*/
コードを編集して実行