任何人都能解释rvalues,左值,POD和非POD方面的细节,下面标记的第一个表达式不正确而下面标记的第二个表达式是否正常?根据我的理解,int()和A()都应该是rvalues,不是吗?
struct A {};
int main()
{
int i;
A a;
int() = i; //Not OK (error).
A() = a; //OK.
return 0;
}
Run Code Online (Sandbox Code Playgroud) 即将推出的C++标准C++ 0x的一个很酷的新特性是"右值引用".右值引用类似于左值(正常)引用,但它可以绑定到临时值(通常,临时值只能绑定到const引用):
void FunctionWithLValueRef(int& a) {...}
void FunctionWithRValueRef(int&& a) {...}
int main() {
FunctionWithLValueRef(5); // error, 5 is a temporary
FunctionWithRValueRef(5); // okay
}
Run Code Online (Sandbox Code Playgroud)
那么,为什么他们发明了一种全新的类型,而不仅仅是删除对普通引用的限制以允许它们绑定到临时版本?
假设定义:
int i = 10;
int *p = &i;
Run Code Online (Sandbox Code Playgroud)
为什么*pa有效左值:
*p+=10;
Run Code Online (Sandbox Code Playgroud)
不应该*p计算存储在&i的int的值,即.10,因此生成"非左值"错误?
我有一个传统的C lib,而function(setsockopts)想要一个指针参数.在C++ 11(gcc 4.8)中,我可以在不初始化命名变量的情况下传递此参数吗?
我有以下不满意的解决方案:
#include <iostream>
#include <memory>
int deref(int const * p) {return * p;}
using namespace std;
int main() {
int arg = 0; cout << deref(& arg) << endl;
// works, but is ugly (unnecessary identifier)
cout << deref(& 42) << endl;
// error: lvalue required as unary ‘&’ operand
cout << deref(& * unique_ptr<int>(new int(42))) << endl;
// works, but looks ugly and allocates on heap
}
Run Code Online (Sandbox Code Playgroud) 我不明白左边缘子程序的用途是什么?用普通子程序无法完成的是什么?你能发一些例子吗?
谢谢
这是C++ 0x右值引用和临时值的后续问题
在上一个问题中,我询问了这段代码应该如何工作:
void f(const std::string &); //less efficient
void f(std::string &&); //more efficient
void g(const char * arg)
{
f(arg);
}
Run Code Online (Sandbox Code Playgroud)
由于隐式临时似乎应该调用移动重载,这种情况发生在GCC中,而不是MSVC(或MSVC的Intellisense中使用的EDG前端).
这段代码怎么样?
void f(std::string &&); //NB: No const string & overload supplied
void g1(const char * arg)
{
f(arg);
}
void g2(const std::string & arg)
{
f(arg);
}
Run Code Online (Sandbox Code Playgroud)
看来,基于我之前问题的答案,该函数g1是合法的(并且被GCC 4.3-4.5接受,但不被MSVC接受).但是,GCC和MSVC都拒绝,g2因为第13.3.3.1.4/3条禁止左值绑定到rvalue ref参数.我理解这背后的基本原理 - 在N2831"使用右值参考修复安全问题"中对此进行了解释.我也认为GCC可能正如该论文的作者所预期的那样实施该条款,因为GCC的原始补丁是由其中一位作者(Doug Gregor)撰写的.
但是,我不是很直观.对我来说,(a)a const string &在概念上更接近于string &&a const char *,而且(b)编译器可以创建一个临时字符串g2,就好像它是这样编写的:
void g2(const std::string & …Run Code Online (Sandbox Code Playgroud) 我在打印从函数返回的结构的成员时遇到问题:
#include <stdio.h>
struct hex_string
{
char a[9];
};
struct hex_string to_hex_string_(unsigned x)
{
static const char hex_digits[] = "0123456789ABCDEF";
struct hex_string result;
char * p = result.a;
int i;
for (i = 28; i >= 0; i -= 4)
{
*p++ = hex_digits[(x >> i) & 15];
}
*p = 0;
printf("%s\n", result.a); /* works */
return result;
}
void test_hex(void)
{
printf("%s\n", to_hex_string_(12345).a); /* crashes */
}
Run Code Online (Sandbox Code Playgroud)
该printf呼叫内to_hex_string_打印出正确的结果,但printf调用内部test_hex崩溃我的程序.究竟是为什么呢?这是一生的问题,还是别的什么?
当我用这个替换printf …
鉴于类型A,B,我关注的是确切的定义std::common_type<A,B>,忽略了std::common_type<A...>任意类型的可变参数A....所以让
using T = decltype(true ? std::declval<A>() : std::declval<B>());
using C = std::common_type<A,B>;
Run Code Online (Sandbox Code Playgroud)
现在,根据一些消息来源,我发现了以下关系(typename为简洁而省略):
cppreference.com: C::type = std::decay<T>::type
cplusplus.com: C::type = T
GCC 4.8.1 <type_traits>实施: C::type = std::decay<T>::type如果T有效,否则C不包含::type成员("SFINAE友好")
Clang 3.3 <type_traits>实施: C::type = std::remove_reference<T>::type
我找到"SFINAE友好"版本的GCC的一个小细节,而std::remove_reference和std::decay实际上仅在内置阵列和功能,加上CV-资格有所区别,这再次我不关心了.所以我的问题是
应该是decay<T>::type还是只是T?使用的理由是decay<T>::type什么?它只是关于表示结果,A() + B()例如算术表达式吗?
例如,尝试了一下,我发现在"正义T"定义的情况下,我们有
common_type<int&,int&> = int&
common_type<int&,long&> = long …Run Code Online (Sandbox Code Playgroud) 这是所有“分配的左操作数所需的左值”错误问题的反函数。
我有一个重载operator []的类,但是只有返回临时类的版本。如果要返回一个整数:
struct Foo
{
int operator[]( int idx ) const { return int( 0 ); }
};
Foo f;
f[1] = 5;
Run Code Online (Sandbox Code Playgroud)
我会正确地得到左值编译器错误。但是,如果返回结构类型,则编译器(在本例中为GCC 7.2)一点也不抱怨:
struct Bar {};
struct Foo
{
Bar operator[]( int idx ) const { return Bar(); }
};
Foo f;
f[1] = Bar();
Run Code Online (Sandbox Code Playgroud)
如果Bar是临时的并且没有专门的运算符=,为什么不以同样的方式抱怨呢?另一个问题,有什么办法可以使这个抱怨?显然,如果以这种方式使用,这是一个编码错误
我正在阅读托马斯·贝克尔关于右值参考及其使用的文章.在那里,他定义了他称之为if-it-a-name规则:
声明为右值引用的事物可以是左值或右值.区别标准是:如果它有一个名字,那么它就是一个左值.否则,它是一个右值.
这对我来说听起来很合理.它还清楚地标识了右值参考的右值.
我的问题是:
lvalue ×10
c++ ×7
c++11 ×5
rvalue ×3
c ×2
arrays ×1
perl ×1
pod ×1
pointers ×1
return-value ×1
struct ×1
subroutine ×1
type-traits ×1