質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
g++

g++はGNUコンパイラコレクション(gcc)のC++コンパイラーです。

コンストラクタ

オブジェクト指向言語において、オブジェクトを生成時に呼び出され、データの初期化などを行なう関数・メソッドのことである。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

3回答

2252閲覧

ムーブコンストラクタとコピーコンストラクタの挙動の違いについて

jun6231jp

総合スコア1

g++

g++はGNUコンパイラコレクション(gcc)のC++コンパイラーです。

コンストラクタ

オブジェクト指向言語において、オブジェクトを生成時に呼び出され、データの初期化などを行なう関数・メソッドのことである。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2020/07/24 15:08

C++でムーブコンストラクタとコピーコンストラクタの挙動の違いを知りたい

C++で右辺値参照、左辺値参照の基本的な動きを学ぼうとしています。
右辺値参照と左辺値参照の違いはムーブコンストラクタとコピーコンストラクタを明確に分離するものだと文献で読んだため、これらのコンストラクタの挙動を調べるためのサンプルコードを書いたのですが、挙動の違いが見られません。

該当のソースコード

#include <iostream> using namespace std; class A { public: int num = 0; A() { std::cout << "Constructor " << std::endl; } A(const A &a) { cout << "Copy Constructor " << std::endl; num=a.num; } A(A &&a) noexcept { std::cout << "Move Constructor " << std::endl; num=a.num; } ~A() { std::cout << "Destructor " << std::endl; } }; int main() { A a1; a1.num=1; A a2; a2.num=2; A b(a1); A c(move(a2)); cout << &a1.num << " " << a1.num << endl; cout << &a2.num << " " << a2.num << endl; cout << &b.num << " " << b.num << endl; cout << &c.num << " " << c.num << endl; a1.~A(); cout << "a1 delete" << endl; a2.~A(); cout << "a2 delete" << endl; cout << &b.num << " " << b.num << endl; cout << &c.num << " " << c.num << endl; return 0; // call destructor }

試したこと

a1というオブジェクトを作成しbにコピー、
a2というオブジェクトを作成しcにムーブするコードです。

コピーとムーブで何も違いが見られず、
どのように挙動の違いを確認すればよいのか、
根本的なことから誤解しているのかアドバイスをいただきたいです。

補足情報

g++のバージョンは下記です。

g++ (Ubuntu 9.3.0-10ubuntu2) 9.3.0
Copyright (C) 2019 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ベストアンサー

こんにちは。

コピーとムーブで何も違いが見られず、

記述されている2つのコンストラクタは同じ処理をしていますので、当然ですが同じ振る舞いをします。

C++は引数の型が異なれば、同じ名前の異なる関数を定義できます。オーバーロードですね。
左辺値参照と右辺値参照は異なる型ですので、それぞれを受け取る異なる関数を定義できます。それだけの話です。つまり、それぞれの関数の振る舞いを決めるのはあなたなのです。


とはいえ本当に自由に書いてしまうとコードが分かりにくくなるので、左辺値参照を受け取る関数はコピー、右辺値参照を受け取る関数はコピーというよりは移動(リソースの所有権を移動することが多いです。)と呼んだ方が妥当な処理を書くことが「強く」推奨されます。

例えば、get()とset()という関数があったら、一般にget()で値を取り出し、set()で値を設定すると思います。それを逆にする(get()で値を設定し、set()で値を取り出す)ことも可能ですが、本当にそんなコードを書いたら激しく非難されると思います。そのようなものとご理解下さい。

投稿2020/07/24 15:54

編集2020/07/24 17:50
Chironian

総合スコア23272

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

copyとmoveの挙動が異なる例

C++

1#define _CRT_SECURE_NO_WARNINGS 2#include <iostream> 3#include <cstring> 4using namespace std; 5class A { 6 char* str_; 7public: 8 A(const char* str) { 9 std::cout << "ctor \n"; 10 str_ = new char [strlen(str)+1]; 11 strcpy(str_, str); 12 } 13 A(const A& a) { 14 cout << "copy ctor" << std::endl; 15 str_ = new char[strlen(a.str_) + 1]; // a.str_ を 16 strcpy(str_, a.str_); // コピーする 17 } 18 A(A&& a) noexcept { 19 std::cout << "move ctor\n"; 20 str_ = a.str_; // a.str_ を盗んで 21 a.str_ = nullptr; // 空にしておく 22 } 23 ~A() { 24 std::cout << "dtor: " << (str_ == nullptr ? "(null)" : str_) << std::endl; 25 delete[] str_; 26 } 27}; 28 29int main() { 30 { 31 cout << "\ncopy:\n"; 32 A x("apple"); 33 A y(x); 34 } 35 cout << "--------------\n"; 36 { 37 cout << "move:\n"; 38 A x("apple"); 39 A y(move(x)); 40 } 41}

実行結果:

copy: ctor copy ctor dtor: apple dtor: apple -------------- move: ctor move ctor dtor: apple dtor: (null)

ま、そーゆーわけで move だと move元のメモリ領域をまるっとかっぱらうから領域確保とコピーの手間が省け、そんだけ速いってことですわー

投稿2020/07/25 00:15

編集2020/07/25 13:44
episteme

総合スコア16614

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

コピーコンストラクタとムーブコンストラクタの違いはそれが起動される文脈が異なるというだけです。 それぞれの文脈に合わせて実際にどのような挙動にするかはあなたが定義することであって、同じ定義をすれば同じ挙動になります。

ムーブの一般的な実装としては、データの実態をポインタによる間接参照にしておいてそれを交換するというものです。

投稿2020/07/24 15:40

SaitoAtsushi

総合スコア5437

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問