§3.10第9节说"非类别rvalues总是有cv不合格类型".这让我很奇怪......
int foo()
{
return 5;
}
const int bar()
{
return 5;
}
void pass_int(int&& i)
{
std::cout << "rvalue\n";
}
void pass_int(const int&& i)
{
std::cout << "const rvalue\n";
}
int main()
{
pass_int(foo()); // prints "rvalue"
pass_int(bar()); // prints "const rvalue"
}
Run Code Online (Sandbox Code Playgroud)
根据标准,对于非类型类型没有const rvalue,但bar()更喜欢绑定const int&&.这是编译器错误吗?
编辑:显然,this也是一个const rvalue :)
编辑:这个问题似乎在g ++ 4.5.0中得到修复,现在两行打印"rvalue".
考虑以下.
#include <string>
using std::string;
string middle_name () {
return "Jaan";
}
int main ()
{
string&& danger = middle_name(); // ?!
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这不会计算任何东西,但它编译时没有错误,并演示了一些让我感到困惑的事情:danger是一个悬空引用,不是吗?
只是想知道文字字符串是左值还是左值.其他文字(如int,float,char等)是左值还是右值?
函数的返回值是左值还是右值?
你怎么说出差异?
在C++中,预增量运算符给出左值,因为返回了递增的对象本身,而不是副本.但在C中,它给出了右值.为什么?
我想将一个rvalue传递std::bind给一个在C++ 0x中采用rvalue引用的函数.我无法弄清楚该怎么做.例如:
#include <utility>
#include <functional>
template<class Type>
void foo(Type &&value)
{
Type new_object = std::forward<Type>(value); // move-construct if possible
}
class Movable
{
public:
Movable(Movable &&) = default;
Movable &operator=(Movable &&) = default;
};
int main()
{
auto f = std::bind(foo<Movable>, Movable());
f(); // error, but want the same effect as foo(Movable())
}
Run Code Online (Sandbox Code Playgroud) 我试图理解为什么有人会编写一个带有const右值引用的函数.
在下面的代码示例中,const rvalue引用函数的用途是什么(返回"3").为什么重载决策首选const Rvalue高于const LValue引用函数(返回"2").
#include <string>
#include <vector>
#include <iostream>
std::vector<std::string> createVector() { return std::vector<std::string>(); }
//takes movable rvalue
void func(std::vector<std::string> &&p) { std::cout << "1"; }
//takes const lvalue
void func(const std::vector<std::string> &p) { std::cout << "2"; }
//takes const rvalue???
//what is the point of const rvalue? if const I assume it is not movable?
void func(const std::vector<std::string> &&p) { std::cout << "3"; }
int main()
{
func(createVector());
return 0;
}
Run Code Online (Sandbox Code Playgroud) 返回结构的函数调用是一个rvalue表达式,但它的成员呢?
这段代码适用于我的g ++编译器,但是gcc给出了一个错误,说"左值作为赋值的左操作数":
struct A
{
int v;
};
struct A fun()
{
struct A tmp;
return tmp;
}
int main()
{
fun().v = 1;
}
Run Code Online (Sandbox Code Playgroud)
gcc视为fun().v右值,我能理解.
但是g ++并不认为赋值表达式是错误的.这是否意味着fun1().v是C++中的左值?
现在的问题是,我搜索了C++ 98/03标准,没有找到关于fun().v是左值还是左值的说法.
那么,它是什么?
我想知道我的构造者最好的形式.以下是一些示例代码:
class Y { ... }
class X
{
public:
X(const Y& y) : m_y(y) {} // (a)
X(Y y) : m_y(y) {} // (b)
X(Y&& y) : m_y(std::forward<Y>(y)) {} // (c)
Y m_y;
}
Y f() { return ... }
int main()
{
Y y = f();
X x1(y); // (1)
X x2(f()); // (2)
}
Run Code Online (Sandbox Code Playgroud)
据我所知,这是编译器在每种情况下都能做到的最好的.
(1a)y被复制到x1.m_y(1份)
(1b)将y复制到X的构造函数的参数中,然后复制到x1.m_y(2个副本)
(1c)y移入x1.m_y(1移动)
(2a)将f()的结果复制到x2.m_y(1份)
(2b)将f()构造成构造函数的参数,然后复制到x2.m_y(1个副本)
(2c)在堆栈上创建f(),然后移入x2.m_y(1 move)
现在几个问题:
在这两个方面,传递const引用并不差,有时候比传递值更好.这似乎违背了"想要速度?通过价值"的讨论..对于C++(不是C++ 0x),我应该坚持使用const引用作为这些构造函数,还是应该通过值传递?对于C++ 0x,我应该通过rvalue引用传递值吗?
对于(2),如果临时直接构造成x.m_y,我更喜欢.我认为即使是rvalue版本也需要一个移动,除非对象分配动态内存,否则移动与复制一样多.有没有办法对此进行编码,以便允许编译器避免这些副本和移动?
我已经在我认为编译器可以做得最好的事情和我自己的问题中做了很多假设.如果不正确,请更正其中任何一项.
§5.3.1一元运算符,第3节
一元&运算符的结果是指向其操作数的指针.操作数应为左值或限定ID.
在这种情况下,"应该"究竟是什么意思?这是否意味着取一个临时的地址是错误的?我只是想知道,因为g ++只给我一个警告,而comeau拒绝编译以下程序:
#include <string>
int main()
{
&std::string("test");
}
Run Code Online (Sandbox Code Playgroud)
g ++ 警告:taking address of temporary
comeau 错误:expression must be an lvalue or a function designator
有人有微软编译器或其他编译器,可以测试这个程序吗?提前致谢.
如果编译器可以证明左值不会再次使用,它是否可以进行自动左值到右值转换?这是一个澄清我的意思的例子:
void Foo(vector<int> values) { ...}
void Bar() {
vector<int> my_values {1, 2, 3};
Foo(my_values); // may the compiler pretend I used std::move here?
}
Run Code Online (Sandbox Code Playgroud)
如果将a std::move添加到注释行,则可以将矢量移动到Foo参数中,而不是复制.但是,正如所写,我没有使用std::move.
静态地证明my_values在注释行之后不会被使用,这很容易.那么编译器允许移动向量,还是需要复制它?