C++ 构造的字符串(“普通旧C链”)是右值吗?
我想知道在下面调用C++ 构造的字符串(“普通旧C链”)是右值吗?,c++,C++,我想知道在下面调用foo(string)时是否省略了复制。 (注意:foo(string)属于我无法更改的接口) 为此,我尝试检查构造的字符串(“helloworld!”)是否是右值 我搜索了如何以编程方式执行此操作,并找到以下帖子: 我想我会得到true到is\u rvalue\u reference:value 我错在哪里 string(“Hello world!”)可能是rvalue,但似乎不是“任何类型的引用”(lvalue,rvalue,universal…),因此我得到了false
foo(string)
时是否省略了复制。
(注意:foo(string)
属于我无法更改的接口)
为此,我尝试检查构造的字符串(“helloworld!”)
是否是右值
我搜索了如何以编程方式执行此操作,并找到以下帖子:
我想我会得到true
到is\u rvalue\u reference:value
- 我错在哪里
string(“Hello world!”)
可能是rvalue
,但似乎不是“任何类型的引用”(lvalue
,rvalue
,universal…),因此我得到了false
结果。如果出现右值
,是否有办法获得真
答案
- 在他的例子中是否存在抄袭省略
- 我错在哪里
std::string(“”)
是右值,但decltype(std::string(“”)
不是右值引用。std::string
对象的类型是<代码>标准::字符串
,当然
您有一个类别错误。右值是一种表达式,右值引用是一种类型
临时字符串
对象是右值。类型字符串&
是右值引用类型
您的decltype
表达式对于您尝试执行的操作没有用处。考虑:
std::string s;
using type1 = decltype(s);
using type2 = decltype(std::string(""));
static_assert(std::is_same<type1, type2>::value, "same");
这将告诉您是否可以将右值引用绑定到对象。但这是一个愚蠢的问题:当然,您可以将类型为X&&的右值引用绑定到类型为X的临时值。您永远不需要问这个问题
不管怎样,函数不接受类型为string&
的参数,因此询问该问题甚至不会告诉您有关调用foo(std::string)
的任何信息
- 在他的例子中是否存在抄袭省略
T&
decltype(string(“”)
的计算结果为string
,而不是string&
——因此它不是右值引用
上述代码之所以有效,是因为:
- 对于xvalue和prvalue,
被推断为T&&
T&&
被推断为T&
,否则(即对于左值)T&
在他的例子中是否存在抄袭省略 在C++14中,允许编译器删除示例中的副本(但不是必需的) (感谢Jonathan Wakely识别了下面引用的相关C++14标准草案引用。) 相关C++14标准草案()引用:
- §12.8[类别副本]第31页 当满足某些条件时,允许实现省略类的复制/移动构造 对象,即使为复制/移动操作选择了构造函数和/或为对象选择了析构函数 有副作用。在这种情况下,实现将处理省略的复制/移动的源和目标 操作作为简单的两种不同的方式引用同一对象,并销毁该对象 在两个对象在没有优化的情况下会被销毁的时间较晚时发生。这种复制/移动操作的省略称为复制省略,在以下情况下是允许的 可组合使用以消除多个副本): [……] [p.31.3]未绑定到引用的临时类对象将被复制/移动时 对于具有相同cv类型的类对象,可以通过 将临时对象直接构造到省略的复制/移动的目标中
- §5.2.2[expr.call]p.4 调用函数时,每个参数应使用其对应的 论点[…]在 在初始化参数时,一个实现可以通过 将相关参数的转换和/或临时结构与 参数的初始化。[……]
ISO/IEC。(2014). ISO国际标准ISO/IEC 1488∶2014(E)-程序设计语言C++。[工作草案]。瑞士日内瓦:国际标准化组织(ISO)。(从中检索)您能为删减部分添加一个标准引用吗?我在[class.copy.elision]中找不到合适的。该标准规定了何时允许省略(其他地方不允许省略,否则将是不一致的实现)。编译器应该尽可能省略。并非所有编译器都这样做。GCC、Clang和Intel都以elide作为链接示例。这就是为什么我说“不应该”。不是“不会”。我的意思和我写的一模一样。然后写下你自己的答案。问题是“是否存在拷贝省略”,我的coliru演示显示存在。我说应该有省略,这与公认的规范写作一致,意味着可以预期的东西,但不是必需的。“应该”一词并不意味着“应该”
Hello world!
0
std::string s;
using type1 = decltype(s);
using type2 = decltype(std::string(""));
static_assert(std::is_same<type1, type2>::value, "same");
std::is_convertible<decltype(std::string("")), std::string&&>::value
is_same<decltype(string("Hello world!")), string>::value // true
template <typename T>
using is_rvalue = std::is_rvalue_reference<T&&>;
is_rvalue<decltype(string(""))>::value // true
is_rvalue<decltype(std::declval<string&&>())>::value // true
is_rvalue<decltype(std::declval<string&>())>::value // false