我正在阅读复制文章(以及它应该如何在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;
并始终返回那个或将案例A
和B
写为return string("1")
等)"1"
是暂时的,但我假设它被用作std::string
的构造函数的参数return{}
,这会是更好的选择吗?)答案 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);
这可以通过以下两种方式之一实现:
只构建了一个std::string
个对象,j
。 (该副本已被删除。)
构造一个临时std::string
对象,将其值复制到j
,然后销毁临时对象。 (该函数返回复制的临时值。)