Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/152.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/flash/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 构造的字符串(“普通旧C链”)是右值吗?_C++ - Fatal编程技术网

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)
的任何信息

  • 在他的例子中是否存在抄袭省略
是的,从临时字符串初始化函数参数不应该进行任何复制或移动,它们应该被省略。C++14标准在[class.copy]第31页中指出,当临时对象(未绑定到引用)复制/移动到同一类型的类对象时,可以省略复制/移动。从相同类型的临时变量初始化类类型的函数参数时,满足该条件。不执行这种省略的编译器(至少在启用优化时,或在“发布”版本中)是一个糟糕的编译器

这里有一个关于复制省略规则的解释--请参阅关于无名临时文件的部分

我错在哪里

右值引用具有以下形式:
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