web-dev-qa-db-ja.com

関数からベクトルを返すのはなぜですか?

このコードを検討してください。私はこのタイプのコードを何度か見ました。 wordsはローカルベクトルです。関数からそれをどのように返すことができますか?死なないことを保証できますか?

 std::vector<std::string> read_file(const std::string& path)
 {
    std::ifstream file("E:\\names.txt");

    if (!file.is_open())
    {
        std::cerr << "Unable to open file" << "\n";
        std::exit(-1);
    }

    std::vector<string> words;//this vector will be returned 
    std::string token;

    while (std::getline(file, token, ','))
    {
        words.Push_back(token);
    }

    return words;
}
106
Pranit Kothari

死なないことを保証できますか?

参照が返されない限り、そうすることはまったく問題ありません。 wordsは、結果を受け取る変数に移動されます。

ローカル変数はスコープ外になります。移動(またはコピー)した後。

66

C++ 11より前:

この関数はローカル変数ではなく、そのコピーを返します。ただし、実際のコピーアクションが行われない最適化をコンパイラが実行する場合があります。

詳細については、 この質問と回答 を参照してください

C++ 11:

関数は値を移動します。詳細については this answer を参照してください

101
Tim Meyer

関数から配列を返すことが許可されていない(または少なくとも期待どおりに動作しない)というC(およびC++)の問題に言及していると思います-これは配列の戻りが(あなたがそれを書く場合単純な形式)スタック上の実際の配列へのポインターを返し、関数が戻るとすぐに削除されます。

しかし、この場合、std::vectorはクラスであり、構造体のようなクラスは呼び出し側のコンテキストにコピーできるため(そして、コピーされるので)機能します。 [実際、ほとんどのコンパイラーは、「戻り値の最適化」と呼ばれるものを使用してこの特定のタイプのコピーを最適化します。オブジェクトに対して割り当てコンストラクタが呼び出されたかのように振る舞います]

返される関数内にあるものへのポインタまたは参照を返さない限り、問題ありません。

24
Mats Petersson

動作をよく理解するには、次のコードを実行できます。

#include <iostream>

class MyClass
{
  public:
    MyClass() { std::cout << "run constructor MyClass::MyClass()" << std::endl; }
    ~MyClass() { std::cout << "run destructor MyClass::~MyClass()" << std::endl; }
    MyClass(const MyClass& x) { std::cout << "run copy constructor MyClass::MyClass(const MyClass&)" << std::endl; }
    MyClass& operator = (const MyClass& x) { std::cout << "run assignation MyClass::operator=(const MyClass&)" << std::endl; }
};

MyClass my_function()
{
  std::cout << "run my_function()" << std::endl;
  MyClass a;
  std::cout << "my_function is going to return a..." << std::endl;
  return a;
}

int main(int argc, char** argv)
{
  MyClass b = my_function();

  MyClass c;
  c = my_function();

  return 0;
}

出力は次のとおりです。

run my_function()
run constructor MyClass::MyClass()
my_function is going to return a...
run constructor MyClass::MyClass()
run my_function()
run constructor MyClass::MyClass()
my_function is going to return a...
run assignation MyClass::operator=(const MyClass&)
run destructor MyClass::~MyClass()
run destructor MyClass::~MyClass()
run destructor MyClass::~MyClass()
12
Caduchon