2016-09-22 61 views
3

我有一个函数:这里所做的操作的确切顺序是什么?

std::string makeMeat() { return "Pork"; } 

而且某处代码,我使用这种方式:

std::string meat = makeMeat(); 

我想知道的是这行代码进行的操作的确切顺序。假设两种不同的情况:

  1. 的std :: string有没有转移构造函数(只是举例)
  2. 的std :: string具有移动构造

我猜makeMeat()创建std::string类的临时对象。

std::string temp("Pork"); 

std::string meat对象被创建后,并通过从temp对象数据的拷贝构造函数初始化?

std::string meat(temp); 

最后temp对象被破坏?

我认为如果没有返回值优化,就会发生这种情况。 如果是这样会怎样?

+6

这是非常简单的测试自己。您可以使用所需的构造函数和函数创建自己的类,而不是使用'std :: string',它们在被调用时会打印一条消息。然后你可以看到自己会发生什么。 –

+4

@JoachimPileborg有了像复制elision这样的东西,我会说“自己尝试一下”的确会给你一个答案,但是并不能反映出所有必须发生的事情,可能发生的事情,需要提供的东西等。 – Angew

回答

2

您可以测试此使用自定义结构:

struct S { 
    S (const char *); 
    S (S const&) = default; 
    S (S&&) = default; 
    virtual ~S(); 
}; 

S get_s() { return "S"; } 

int main() { 
    S s = get_s(); 
} 

没有选项,G ++会的Elid最构造打电话这段代码等同于:

S s("S"); 

所以只能从const char *构造是调用。现在

,如果你告诉G ++不构造的Elid(-fno-elide-constructors),有三个构造函数/析构函数调用:

  1. 第一个创建一个临时S("S");
  2. 第二个在get_s,S(S&&)内创建临时;
  3. 然后调用第一个临时解析器;
  4. 然后移动构造函数在main之内调用;
  5. 然后调用get_s返回的临时析构函数;
  6. 然后调用s的析构函数。

如果S没有移动构造函数,那么可以简单地用上面列表中的复制构造函数替换移动构造函数。

+0

您能否介绍一下关于第二步的更多内容?它是否创建了一个实际“返回”到主流的对象? – vector2718

+0

@ vector2718内存中有三个地方在这个过程中为'S'对象分配存储空间:A)在主函数中,B)在get_s的“调用栈”中,C)在' get_s'。对象S(“S”)'首先在'C'中构造,然后在返回位置'B'中移动,然后在其目标位置'A'处移动。 – Holt

+0

我明白C)作为get_s的堆栈框架,它存储了该函数的所有参数和局部变量。但是,get_s的“call stack”是什么意思? – vector2718

3

该字符串直接在meat中构建。不存在具有独特生命的临时存在。这被称为elision。

这种行为是在C++ 17规定,并在实践中任何合理的现代化生产品质的现代编译器的情况与设定C++ 03 11和14

在C++ 14无病理构建标志而且之前,班级必须有一个移动或复制ctor才能发生上述情况,否则您将获得构建中断。所有构造函数中的代码都不会运行。

古代或玩具编译器,或带有病态标志的编译器告诉他们不要退缩,可能会制造多达2个临时对象,并且会混淆副本。这种情况并不令人感兴趣,因为病态编译器状态同样可以自由实现a+=b;(与ab整数类型)作为for (i from 0 to b)++a;!你应该诚实地考虑缺乏elision同样的病态。

C++中的Elision指的是标准允许的对象生命周期和标识合并。因此,在某种意义上,3个字符串(函数,返回值和从返回值构造的值的临时字符)存在时,它们的身份会合并为一个具有统一生命周期的对象。

+0

不确定,但是:'“Pork”'不是'std :: string'类型的值,因此编译器不需要在C++ 17中执行copy elision。 – Holt

+0

@holt但我们构造了一个类型为'std :: string'的prvalue从*'“Pork”返回那里*,返回那个,不是?不完全确定,但如果不是真的,我会感到失望。 – Yakk

+0

@Holt:编译器永远不会*“required”*来执行copy-elision。只有“允许”才能这样做。 – Nawaz