下面
int main
中有六行正在创建和初始化变量;在这些场景中的哪些(如果有)中,会为作业创建副本?
此外,在
sixthMap
的情况下,是否会发生任何奇怪的事情,因为我们使用带有&符号的自动推导,但它调用的函数也返回一个引用?
std::unordered_map<std::string, std::vector<std::string>>
createStdObject()
{
std::unordered_map<std::string, std::vector> newUnorderedMap
{
{"A", {"first", "vector", "in", "map"},
{"B", {"second", "vector", "in", "map"}
};
return newUnorderedMap;
}
std::unordered_map<std::string, std::vector<std::string>>&
createStdObjectWithReference()
{
std::unordered_map<std::string, std::vector> newUnorderedMap
{
{"A", {"first", "vector", "in", "map"},
{"B", {"second", "vector", "in", "map"}
};
return newUnorderedMap;
}
int main()
{
std::unordered_map<std::string, std::vector> firstMap = newUnorderedMap();
std::unordered_map<std::string, std::vector> secondMap = createStdObjectWithReference();
const auto thirdMap = newUnorderedMap();
const auto& fourthMap = newUnorderedMap();
const auto fifthMap = createStdObjectWithReference();
const auto& sixthMap = createStdObjectWithReference();
}
根据我有限的知识,我的猜测是:
firstMap
和 thirdMap
可以是 newUnorderedMap()
sixthMap
自动声明中的&符号基本上会被忽略,并且sixthMap
在类型和行为方面与fifthMap
相同另一方面,在编译时本身显然没有任何返回值实际上需要被复制,因此我认为没有理由它们不应该全部导致移动分配
忽略你的代码有很多(我认为是)打字错误,你无法理解的是 C++ 中最基本的概念之一:对象生命周期。用不精确的方式简单解释一下(为了理解):
在堆栈上(即本地)创建的每个对象都有其作用域。一旦退出该范围,在该范围内创建的所有对象都将被销毁。此外,每个函数都是一个作用域,这意味着函数中创建的每个对象一旦到达函数末尾就会停止存在。因此,在函数内部创建的对象“比函数更长寿”的唯一方法是将它们复制/移动到函数外部的某个地址。
看似例外的是名为“复制省略”的东西。当您的函数按值返回,并且返回的对象是在该函数中创建的时,将不会涉及复制/移动,并且看起来您新创建的对象逃脱了其范围。然而,实际上,您的对象实际上是在调用站点上创建的,位于该函数的范围之外,而函数仅用于初始化已创建的对象。粗略地说,这就是复制省略的意思。它归结为复制指针,但没有调用构造函数。 因此,有以下代码:
#include <cstdio>
class Lifetime
{
public:
Lifetime() { std::puts("default ctor"); }
Lifetime(Lifetime&&) { std::puts("move ctor"); }
Lifetime(const Lifetime&) { std::puts("copy ctor"); }
~Lifetime() { std::puts("destructor"); }
};
Lifetime make_lifetime() {
Lifetime l{}; // Lifetime object initialized
return l; // Lifetime object not destroyed because created outside the function scope
}
const Lifetime& make_lifetime_ref() {
Lifetime l{}; // Lifetime object created
return l; // Lifetime object destroyed
}
int main() {
const auto lifetime1 = make_lifetime(); // Lifetime object created; copy ctor not called!
// 'make_lifetime_ref' returns a reference to already destroyed object
// const auto lifetime2 = make_lifetime_ref(); // oops! undefined behaviour:
return 0;
}
会产生这样的输出:
$ default ctor
$ destructor
如您所见,不涉及复制。
请注意,
auto
与此无关,即它不会影响复制。因此,在您的情况下,创建
firstMap
、thirdMap
和 fourthMap
不会涉及复制,而其他三个则会导致未定义的行为。另请注意,这都与局部变量有关,其他规则有一些不同。