这个回报声明中发生了什么?

时间:2017-01-18 21:59:27

标签: c++ stl

我正在阅读复制文章(以及它应该如何在C ++ 17中得到保证)这让我有点困惑(我不确定我知道之前我认为的事情)。所以这是一个最小的测试用例:

std::string nameof(int param)
{
    switch (param)
    {
    case 1: 
        return "1"; // A
    case 2: 
        return "2" // B
    }
    return std::string(); // C
}

我看到它的方式,情况A和B对返回值执行直接构造,因此复制省略没有意义,而案例C不能执行复制省略,因为有多个返回路径。 这些假设是否正确

另外,我想知道是否

  • 有一种更好的方式来编写上述内容(例如,有一个std::string retval;并始终返回那个或将案例AB写为return string("1")等)
  • 发生了任何移动,例如"1"是暂时的,但我假设它被用作std::string的构造函数的参数
  • 我提出了一些优化问题(例如,我认为C可以写成return{},这会是更好的选择吗?)

2 个答案:

答案 0 :(得分:3)

要使其对NRVO友好,您应该始终返回相同的对象。对象的值可能不同,但对象应该是相同的。

然而,遵循上述规则会使程序更难阅读,并且通常应该选择可读性而不是不明显的性能改进。由于std::string定义了一个移动构造函数,因此移动指针和长度之间的区别并没有这么大,我觉得无法在应用程序中注意到这一点。

关于您的上一个问题,return std::string()return {}将完全相同。

您的问题中也有一些不正确的陈述。例如,"1"不是临时的。它是一个字符串文字。临时是从这个文字创建的。

最后但并非最不重要的是,强制性C ++ 17副本省略不适用于此处。它保留用于

之类的情况
std::string x = "X";

在强制要求之前可以生成代码以创建临时std::string并使用复制(或移动)构造函数初始化x

答案 1 :(得分:1)

在所有情况下,副本可能会或可能不会被删除。考虑:

std::string j = nameof(whatever);

这可以通过以下两种方式之一实现:

  1. 只构建了一个std::string个对象,j。 (该副本已被删除。)

  2. 构造一个临时std::string对象,将其值复制到j,然后销毁临时对象。 (该函数返回复制的临时值。)