为什么这样:
#include <string>
#include <iostream>
using namespace std;
class Sandbox
{
public:
Sandbox(const string& n) : member(n) {}
const string& member;
};
int main()
{
Sandbox sandbox(string("four"));
cout << "The answer is: " << sandbox.member << endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
给出输出:
答案是:
代替:
答案是:四
可能重复:
使用forward的优点
我知道它的作用以及何时使用它但我仍然无法理解其工作原理.请尽可能详细,并解释std::forward如果允许使用模板参数推断,何时不正确.
我的一部分困惑是:"如果它有一个名字,它就是一个左值" - 如果是这样的话,为什么std::forward当我通过thing&& xvs 时表现不同thing& x?
假设我使用基于范围的循环编程时的当前规则说
使用
for(auto const &e :...)或for(auto &e:...)在可能时使用for(auto a: ...).
我以我自己的经验和这个问题为例.
但是在读完关于循环的新简洁之后我想知道,我不应该用我&的规则替换我的规则&&吗?正如这里所写,这看起来像迈耶斯的通用参考.
所以,我问自己,如果我的新规则要么
使用
for(auto const &&e :...)或for(auto &&e:...)在可能的时候......
或者这不总是有效,因此应该是相当复杂的
检查
for(auto const &&e :...)或者for(auto &&e:...)是可能的,再考虑for(auto const &e :...)或者for(auto &e:...),并且只在需要时不使用引用.
虽然T&&与模板一起使用作为转发参考或通用引用(如Scott Meyers所称),但我auto&&在代码示例中看到了一些博客.我认为auto自己应该足够了,然而,CbCon 2014中的 Herb Sutter 说:永远不要auto&&用于局部变量
这是为什么?
看到所有回复,我觉得我应该问对方.尽管有一般编码指南,但是在函数体内使用auto &&以获得代码正确性和可维护性是有任何好的用例.
auto&& mytup = std::make_tuple(9,1,"hello");
std::get<0>(mytup) = 42;
cout << std::get<0>(mytup) << endl;
Run Code Online (Sandbox Code Playgroud)
auto&& var =
func()总是使用而不是auto var = func()没有复制/移动?阿基于范围的for声明在§6.5.4定义为等同于:
{
auto && __range = range-init;
for ( auto __begin = begin-expr,
__end = end-expr;
__begin != __end;
++__begin ) {
for-range-declaration = *__begin;
statement
}
}
Run Code Online (Sandbox Code Playgroud)
其中range-init定义了两种基于范围的形式for:
for ( for-range-declaration : expression ) => ( expression )
for ( for-range-declaration : braced-init-list ) => braced-init-list
Run Code Online (Sandbox Code Playgroud)
(该条款进一步规定了其他子表达式的含义)
为什么__range给出推导类型auto&&?我的理解auto&&是,通过传递它来保留表达式的原始值(左值/右值)是有用的std::forward.但是,__range不会通过任何地方std::forward.它得到的范围内时迭代器作为一个人的只用__range,__range.begin()或begin(__range).
使用"通用参考"有auto&&什么好处?还auto&不够吗? …
更新问题为什么这两个右值引用示例有不同的行为?:
源代码:
int a = 0;
auto && b = a++;
++a;
cout << a << b << endl;
Run Code Online (Sandbox Code Playgroud)
版画 20
是否b在a++通话后使用未定义的行为(UB)?也许我们不能使用,b因为它指的是暂时的?
c++ undefined-behavior rvalue-reference language-lawyer c++11
我想知道在这个代码中for (auto& i : v),for (auto&& i : v)在基于范围的for循环之间有什么区别:
#include <iostream>
#include <vector>
int main()
{
std::vector<int> v = {0, 1, 2, 3, 4, 5};
std::cout << "Initial values: ";
for (auto i : v) // Prints the initial values
std::cout << i << ' ';
std::cout << '\n';
for (auto i : v) // Doesn't modify v because i is a copy of each value
std::cout << ++i << ' ';
std::cout << '\n';
for …Run Code Online (Sandbox Code Playgroud) 在C++中,您可以将函数的返回值(返回值,而不是引用)绑定到const引用,代码仍然有效,因为此临时的生命周期将延长到范围结束.例如
std::string get_string() {
return "abc";
}
void f() {
const std::string& str = get_string();
std::cout << str; // valid, str is not dangling reference.
}
Run Code Online (Sandbox Code Playgroud)
我的问题是,什么时候有用,例如何时是代码
A get_a();
const A& a = get_a();
Run Code Online (Sandbox Code Playgroud)
比代码更好
A get_a();
A a = get_a();
Run Code Online (Sandbox Code Playgroud)
以什么方式(例如更快,更小的二进制大小等)?应该是什么A,get_a以及调用后的代码get_a?
我已经手工测试了几个案例,并且在每种情况下它似乎具有相同数量的副本和移动.
让我们将这个问题限制为当前的C++标准,现代版本的编译器和构建并启用了优化(O2,O3或其他编译器的等价物)
假设我正在做一个涉及创建一个我不会修改的临时对象的计算:
auto tmp = val * val;
// Do some calculations with tmp...
Run Code Online (Sandbox Code Playgroud)
此外,我不需要tmp成为左值,因为我不会接受它的地址。
在这种情况下,我应该在代码中使用哪种惯用法:
1. auto tmp = val * val;
2. const auto tmp = val * val;
3. const auto & tmp = val * val;
4. auto && tmp = val * val;
5. const auto && tmp = val * val;
Run Code Online (Sandbox Code Playgroud)
请注意,我明确地放弃了,auto &因为这通常会导致UB。但是,我知道const auto &可以延长temp的寿命,因此在此我将其保留为一种选择。
不出所料,对于这个简单的示例,-O3无论如何都会编译为相同的代码:https : //godbolt.org/z/oXj3hd
但是在一个更复杂的示例中,我想他们不会。
我的想法是,选项3或5可能是最正确的,因为它们将保留对象的恒定性,并且将保留临时对象。
编辑:
许多人提到了一个事实,在这个简单的示例中,甚至不需要命名临时文件。那是正确的。我所追求的是关于生成临时表达式的复杂操作的建议,并将在代码中重复使用。