如果您阅读的代码如下
auto&& var = foo();
where foo是按类型值返回的任何函数T.然后var是左值类型的左值引用T.但这意味着var什么呢?这是不是意味着,我们被允许窃取资源var?是否有任何合理的情况,您应该使用auto&&告诉读者您的代码与您在返回时unique_ptr<>告诉您拥有独占所有权时的行为?例如什么T&&时候T类型?
我只是想了解,如果有任何其他用例auto&&比模板编程中的用例; 喜欢这篇文章中的例子中所讨论的那些通用参考斯科特迈尔斯.
C++ 14草案(N3936)在§3.2/ 3中陈述:
变量x的名称显示为潜在评估的表达式ex,除非将lvalue-to-rvalue转换(4.1)应用于x,否则将生成不调用任何非平凡函数的常量表达式(5.19),并且如果x是一个对象,ex是表达式e的潜在结果集合的元素,其中左值到右值的转换(4.1)应用于e,或者e是丢弃值表达式(第5节).
这对我没有任何意义:如果表达式e是丢弃值表达式取决于使用的上下文e.表达式语句(第6.2节)中使用的每个表达式都是一个丢弃值表达式.如果左值到右值转换被施加到e还依赖于上下文e中被使用.
而且,表达式在另一个表达式的潜在结果集合中意味着什么.人们需要表达式相等的概念才能确定集合的成员资格.但我们没有参考透明度,所以我看不出如何实现这一点.
为什么从C++ 11改为C++ 14?这怎么解释?就目前而言,它没有意义.
标准状态,即nullptr类型std::nullptr_t(2.14.7)的指针文字.并且18.2p9定义nullptr_t了
namespace std {
typedef decltype(nullptr) nullptr_t;
}
Run Code Online (Sandbox Code Playgroud)
7.1.6.2p4 decltype(nullptr)是表达式的类型,nullptr根据定义std::nullptr_t(因为表达式nullptr是prvalue).将其代入nullptr_t结果的定义中
typedef nullptr_t nullptr_t
Run Code Online (Sandbox Code Playgroud)
另一方面,typedef说明符不引入新类型,它只是另一个现有类型的名称.那么,到底是什么nullptr_t?我无法理解这些定义.
我有一个基类和几个派生类,如下面的代码:
class Base
{
public:
friend bool operator==(const Base&, const Base&);
virtual ~Base(){}
private:
virtual bool equals(const Base& other) const = 0;
};
bool operator==(const Base& lhs, const Base& rhs)
{
return lhs.equals(rhs);
}
class A : public Base
{
public:
A(int x) : x_(x){}
private:
virtual bool equals(const Base& other) const;
int x_;
};
bool A::equals(const Base& other) const
{
const A* pA = dynamic_cast<const A*>(&other);
if(!pA) return false;
return x_ == pA->x_;
}
class B …Run Code Online (Sandbox Code Playgroud) 请考虑以下代码:
struct S
{
int x;
void f()
{
auto l = [&](){ x = 42; }; //this is implicitly captured here
}
};
Run Code Online (Sandbox Code Playgroud)
§5.1.2/ 14指出:
如果隐式捕获实体并且捕获默认值为=,或者使用不包含&的捕获显式捕获实体,则通过副本捕获实体.
因此,我得出结论,这this不是由副本捕获的.但是后来§5.1.2/ 15:
如果实体是隐式或显式捕获但未通过复制捕获,则通过引用捕获实体.未指定是否在闭包类型中为通过引用捕获的实体声明了其他未命名的非静态数据成员.
this是通过参考捕获.但现在§5.1.2/ 17指出:
[...]如果
this被捕获,则每个odr-usethis转换为对闭包类型的相应未命名数据成员的访问,[...]
据我所知,这意味着闭包类型中必须有一个与this指针对应的未命名数据成员.但由于this是通过引用捕获的,因此标准不要求存在这样的成员.我有什么问题?
在SO上已经有类似的问题,但我想强调braced-init-lists的另一个方面.考虑以下:
auto x = {1}; //(1)
Run Code Online (Sandbox Code Playgroud)
除非<initializer_list>包含标题,否则这是不正确的(8.5.4/2).但为什么?标准说,模板std::initializer_list不是预定义的.这是否意味着,声明(1)引入了一种新类型?在所有其他情况下,auto可以使用的地方如
auto y = expr;
Run Code Online (Sandbox Code Playgroud)
where expr是表达式,auto deduces类型已经存在.另一方面,从逻辑的角度来看,编译器必须为构造分配一个implicite类型{1},std::initializer_list然后是另一个名称.但是在声明(1)中我们不想命名这种类型.那么为什么必须包括这个标题.有类似的情况nullptr.它的类型隐含存在,但要明确指出它必须包括<cstddef>.
这是一个语言律师问题。C++11 中的第 5p5 条内容如下:
\n\n\n\n\n如果表达式最初具有类型 \xe2\x80\x9creference to T\xe2\x80\x9d (8.3.2, 8.5.3),则在任何进一步分析之前将类型调整为 T。表达式指定引用所表示的对象或函数,并且表达式是左值或x值,具体取决于表达式。
\n
另一方面,\xc2\xa75.2.2p3 指出:
\n\n\n\n\n如果后缀表达式指定析构函数 (12.4),则函数调用表达式的类型为 void;\n 否则,函数调用表达式的类型为静态选择的函数的返回类型(即,\n 忽略虚函数)关键字),即使实际调用的函数的类型不同。该类型应为对象类型、引用类型或 void 类型。
\n
考虑这段代码:
\n\nint& f();\nf(); // What is the type of this expression?\nRun Code Online (Sandbox Code Playgroud)\n 假设需要实现getter/setter(我也尽量避免使用它们,因为它们通常表示设计不好).以下两种变体哪种更好,每种变体的含义是什么?
可能性(1):
class Foo;
class Bar
{
public:
const Foo& getFoo() const {return foo_;}
private:
Foo foo_;
};
Run Code Online (Sandbox Code Playgroud)
或(2):
class Foo;
class Bar
{
public:
void getFoo(Foo& foo) const {foo = foo_}
private:
Foo foo_;
};
Run Code Online (Sandbox Code Playgroud)
就个人而言,我总是使用第一个变体,因为我发现它更直观.在第二个变体中,您必须在调用getFoo之前构造Foo对象,该对象将保存getFoo的结果,然后向getFoo传递对此对象的引用.这种变体对我来说是违反直觉的,但有些人更喜欢使用secodn变体.出于什么原因,第二个变体可能优于第一个?