我是 C++ 新手,我想了解完美转发如何与 std::move 结合使用.
我定义了一个 std::vector<QueueData> queue()我想使用模板函数填充 fillWithData .由于我花了一些时间研究完美转发,所以我首先要检查我是否理解正确,其次要弄清楚 move 是什么。在此上下文中的行为。
fillWithData是一个可变参数模板函数,感谢 forward , 能够通过折叠规则将参数视为左值或右值。 (Q1 - 是否正确?)
template< class Container, typename ... Args >
static void fillWithData(Container & oDataContainer,
Args&& ... args) // universal reference
{
typedef typename Container::value_type::element_type QueueDataPtr;
oDataContainer.emplace_back(std::forward<Args>(args)...);
}
现在,假设有一个对象 User usr从中获取要传递给 fillWithData 的参数:
如果我调用 fillWithData( queue, usr.getName(), usr.getEmail(), usr.getAddr() )将emplace做以下调用?
如果我想优化我可以利用 move将左值视为右值(Q2 - usr.getName() 是左值吗?):
fillWithData( queue,
std::move(usr.getName()),
std::move(usr.getEmail()),
std::move(usr.getAddr()) )
这样,(Q3)就是直接转发给User的值constructor 并且新对象是直接在vector内部构建的吗?
此外(Q4),例如,如果我再次调用 usr.getName()在调用 fillWithData 之后,数据是否仍然可用? (我想我会有运行时错误)。
最后(Q5),没有 std::move , 实现完美转发有意义吗?
谢谢。
最佳答案
std::move不执行完美转发。它将左值引用转换为右值引用。由于它执行了转换,输入与输出不同 - 所以并不完美。
std::forward<X>执行完美转发,但它需要推导 X 的类型(即它是当前函数的模板参数并且是通用引用)。
有人可能会问为什么 std::move必须在看似右值的引用变量名称上调用。
这是因为任何有名字的变量实际上都是一个左值,不管它是否用 & 声明或两个。
所以...
int&& x = y();是一个左值,它只会绑定(bind)到一个右值(y 必须返回一个右值引用或临时值)。
int& x = y();也是左值,但它将绑定(bind)到左值或右值(y 可能返回 int& 或 int&&)。
在上述情况下,std::move(x)返回一个右值引用。在第一种情况下它会(看似)完美,在第二种情况下它会被转换 - 因此没有完美转发。
std::forward<>检测到差异,而 std::move没有。
总而言之,在推导的上下文中,std::forward<T>(x)将返回与函数参数中传递的 x 完全相同的类别(左值或右值),而 std::move将始终返回右值引用,即使传递了左值引用也是如此。
困惑?有一个简单的经验法则:
给定:
template<class T> void bar(T x); // pass by value
然后:
template<class Deduced> void foo(Deduced&& x)
{
// x is a universal reference in deduced context,
// so we probably want to forward it.
bar(std::forward<Deduced>(x));
}
void foo(Known&& x)
{
// x is definitely an r-value reference. No point forwarding something
// we already know the category of - move it.
bar(std::move(x));
}
void foo(Known x)
{
// x is definitely an l-value. No point forwarding an l-value
// reference, as this will cause an un-necessary copy.
// So we must cast x.
bar(std::move(x));
}
void foo(Known const& x)
{
// x is definitely a const l-value reference. No point forwarding
// a const reference, and no point moving it, since a
// (Known const &&) is not useful.
// Whatever we do, there's going to be a copy.
bar(x);
}
关于c++ - 在此上下文中的完美转发和 std::move 行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42790645/
我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server
我有一个用户工厂。我希望默认情况下确认用户。但是鉴于unconfirmed特征,我不希望它们被确认。虽然我有一个基于实现细节而不是抽象的工作实现,但我想知道如何正确地做到这一点。factory:userdoafter(:create)do|user,evaluator|#unwantedimplementationdetailshereunlessFactoryGirl.factories[:user].defined_traits.map(&:name).include?(:unconfirmed)user.confirm!endendtrait:unconfirmeddoenden
如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:
两个gsub产生不同的结果。谁能解释一下为什么?代码也可在https://gist.github.com/franklsf95/6c0f8938f28706b5644d获得.ver=9999str="\tCFBundleDevelopmentRegion\n\ten\n\tCFBundleVersion\n\t0.1.190\n\tAppID\n\t000000000000000"putsstr.gsub/(CFBundleVersion\n\t.*\.).*()/,"#{$1}#{ver}#{$2}"puts'--------'putsstr.gsub/(CFBundleVersio
我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我
我在一段非常简单的代码(如我所想)中得到了一个错误的值:org=4caseorgwhenorg=4val='H'endputsval=>nil请不要生气,我希望我错过了一些非常明显的东西,但我真的想不通。谢谢。 最佳答案 这是典型的Ruby错误。case有两种被调用的方法,一种是你传递一个东西作为分支的基础,另一种是你不传递的东西。如果您确实在case中指定了一个表达式语句然后评估所有其他条件并与===进行比较.在这种情况下org评估为false和org===false显然不是真的。所有其他情况也是如此,它们要么是真的,要么是假的。
假设您在Ruby中执行此操作:ar=[1,2]x,y=ar然后,x==1和y==2。是否有一种方法可以在我自己的类中定义,从而产生相同的效果?例如rb=AllYourCode.newx,y=rb到目前为止,对于这样的赋值,我所能做的就是使x==rb和y=nil。Python有这样一个特性:>>>classFoo:...def__iter__(self):...returniter([1,2])...>>>x,y=Foo()>>>x1>>>y2 最佳答案 是的。定义#to_ary。这将使您的对象被视为要分配的数组。irb>o=Obje
如果我有以下一段Ruby代码:classBlahdefself.bleh@blih="Hello"@@bloh="World"endend@blih和@@bloh到底是什么?@blih是Blah类中的一个实例变量,@@bloh是Blah类中的一个类变量,对吗?这是否意味着@@bloh是Blah的类Class中的一个变量? 最佳答案 人们似乎忽略了该方法是类方法。@blih将是常量Bleh的类Class实例的实例变量。因此:irb(main):001:0>classBlehirb(main):002:1>defself.blehirb
我有一个数组数组,想将元素附加到子数组。+=做我想做的,但我想了解为什么push不做。我期望的行为(并与+=一起工作):b=Array.new(3,[])b[0]+=["apple"]b[1]+=["orange"]b[2]+=["frog"]b=>[["苹果"],["橙子"],["Frog"]]通过推送,我将推送的元素附加到每个子数组(为什么?):a=Array.new(3,[])a[0].push("apple")a[1].push("orange")a[2].push("frog")a=>[[“苹果”、“橙子”、“Frog”]、[“苹果”、“橙子”、“Frog”]、[“苹果”、“
我经常将预配置的lambda插入可枚举的方法中,例如“map”、“select”等。但是“注入(inject)”的行为似乎有所不同。例如与mult4=lambda{|item|item*4}然后(5..10).map&mult4给我[20,24,28,32,36,40]但是,如果我制作一个2参数lambda用于像这样的注入(inject),multL=lambda{|product,n|product*n}我想说(5..10).inject(2)&multL因为“inject”有一个可选的单个初始值参数,但这给了我......irb(main):027:0>(5..10).inject