【发布时间】:2021-12-25 12:01:29
【问题描述】:
我试图理解 C++ 中复制和移动构造函数的概念。所以尝试不同的例子。下面给出了一个我无法理解其输出的示例:
#include <iostream>
#include <vector>
using namespace std;
struct NAME
{
NAME()
{
std::cout<<"default"<<std::endl;
}
NAME(const NAME& )
{
std::cout<<"const copy"<<std::endl;
}
NAME(NAME& )
{
std::cout<<"nonconst copy"<<std::endl;
}
NAME(NAME &&)
{
std::cout<<"move"<<std::endl;
}
};
void foo(std::pair<std::string, NAME> )
{
}
void foo2(std::vector<std::pair<std::string, NAME>> )
{
}
int main()
{
foo(std::make_pair("an", NAME())); //prints default --> move --> move
std::cout << "----------------------------------------"<<std::endl;
foo({"an", NAME()}); //prints default --> move
std::cout << "----------------------------------------"<<std::endl;
foo2({{"an", NAME()}}); //prints default --> move --> const copy
std::cout << "----------------------------------------"<<std::endl;
return 0;
}
案例1:对于foo(std::make_pair("an", NAME()));
输出
default
move
move
这就是我认为正在发生的事情。
第 1 步。创建了一个 NAME() 类型的临时变量,因为我们已使用 NAME() 的默认构造函数将其传递给 std::make_pair。
第 2 步。使用 std::make_pair 的构造函数之一,它转发(移动)在第一步中创建的临时文件。所以NAME() 的移动构造函数。
第 3 步。最后,由于 foo 的参数是按值传递的,因此在第 2 步中创建的 std::pair 被“移动”(不是“复制”?),进而“移动”@ 987654333@临时最后一次。
案例2:对于foo({"an", NAME()});
输出
default
move
第 1 步。创建一个临时的NAME。
第 2 步。这次由于我们没有 std::make_pair,std::pair 的初始化列表构造函数(如果有)用于“移动”在第 1 步中创建的临时对象。
案例3:对于foo2({{"an", NAME()}});
输出
default
move
const copy
我不知道为什么使用复制构造函数而不是移动构造函数,以及为什么使用const 版本而不是非常量版本的复制构造函数。 p>
我的解释是否正确。请纠正我 在哪里我在任何详细的解释步骤中都错了。
【问题讨论】:
-
非 const 复制构造函数不应该是一个东西。
-
@sweenish 信不信由你,非常量复制构造函数是 C++ 的东西。类 T 的任何构造函数,只要有一个类型为
T &或T const &的强制参数(它还可能有更多的默认参数),都是复制构造函数。 -
@JaMiT 但是如果 initializer_list 使用复制构造函数,那么为什么在案例 2 的第 2 点中使用移动构造函数?也就是说,在我对案例 2 的解释中,请查看第 2 点。还使用了
std::pair的 initializer_list 构造函数,然后还应该使用复制构造函数。
标签: c++ c++11 constructor c++17 copy-constructor