草庐IT

c++ - 命名右值引用

coder 2024-02-15 原文

请原谅我在这个话题上不够清晰。我正在尝试创建用于将大类插入 vector 的函数。在这个例子中,我使用整数 vector 作为大类。

#include <vector>
#include <iostream>
using namespace std;

vector<vector<int>> vectorOfVectors;

void fn(const vector<int> &v) {
    vectorOfVectors.push_back(v);

}
void fn(vector<int> &&v) {
    vectorOfVectors.push_back(std::move(v));
}

int main() {
    vector<int> a({1});
    const vector<int> b({2});
    fn(std::move(a));
    fn(b);
    cout<<b[0];
}

显然,我希望尽可能不进行复制。我的问题:

  1. 这段代码做的事情正确吗?
  2. 有更好的方法吗?
  3. 对于使用自定义类的相同方法,我是否需要定义移动构造函数?

最佳答案

Does this code do the right thing?

是的。 C++11 添加了 std::vector::push_back(T&&)正是出于这个原因。

Is there a better way of doing this?

你的 fn(const vector<int> &v)fn(vector<int> &&v)都在做同样的事情,插入争论vvectorOfVectors 的末尾.代替你的两个fn函数,您可以使用一个使用完美转发的函数模板。

template<typename T>
void fn(T &&v) {
    vectorOfVectors.push_back(std::forward<T>(v));
}

这要归功于 C++11 reference collapsing rulesstd::forward .模板类型T变成 vector<int>&如果v是一个左值但是 vector<int>&&如果v是一个右值。引用折叠规则意味着 vector<int>& &&变成 vector<int>&同时 vector<int>&& &&变成 vector<int>&& .这正是你想要的,调用 push_back 的版本在左值的情况下执行复制,但在右值的情况下执行移动的版本。

一个缺点是,当您出错时,这有时会导致有趣的诊断。 (这里的“有趣”是指来自 g++ 或 clang++ 的数百行高深莫测的诊断文本)。另一个缺点是模板可能会导致“转换器疯狂”的情况。

For the same approach to work with custom classes, do I need to define move constructors?

不一定。如果类没有声明用户定义的析构函数、复制构造函数、复制赋值运算符或移动赋值运算符,您将获得一个隐式声明的移动构造函数。如果类具有不可移动的数据成员或派生自无法移动或删除的类,则隐式声明的移动构造函数将被定义为已删除。

对我来说,这有点太难记了。我不知道这是好习惯还是坏习惯,但我已经开始使用 Foo(const Foo&)=default , 对五个函数的其他规则有类似的声明。我还将构造函数限定为 explicit在许多情况下是为了避免“转换器疯狂”的问题。

关于c++ - 命名右值引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33537355/

有关c++ - 命名右值引用的更多相关文章

  1. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  2. ruby-on-rails - 如何重命名或移动 Rails 的 README_FOR_APP - 2

    当我在我的Rails应用程序根目录中运行rakedoc:app时,API文档是使用/doc/README_FOR_APP作为主页生成的。我想向该文件添加.rdoc扩展名,以便它在GitHub上正确呈现。更好的是,我想将它移动到应用程序根目录(/README.rdoc)。有没有办法通过修改包含的rake/rdoctask任务在我的Rakefile中执行此操作?是否有某个地方可以查找可以修改的主页文件的名称?还是我必须编写一个新的Rake任务?额外的问题:Rails应用程序的两个单独文件/README和/doc/README_FOR_APP背后的逻辑是什么?为什么不只有一个?

  3. ruby - 一个 YAML 对象可以引用另一个吗? - 2

    我想让一个yaml对象引用另一个,如下所示:intro:"Hello,dearuser."registration:$introThanksforregistering!new_message:$introYouhaveanewmessage!上面的语法只是它如何工作的一个例子(这也是它在thiscpanmodule中的工作方式。)我正在使用标准的ruby​​yaml解析器。这可能吗? 最佳答案 一些yaml对象确实引用了其他对象:irb>require'yaml'#=>trueirb>str="hello"#=>"hello"ir

  4. ruby - rails 3 redirect_to 将参数传递给命名路由 - 2

    我没有找到太多关于如何执行此操作的信息,尽管有很多关于如何使用像这样的redirect_to将参数传递给重定向的建议:action=>'something',:controller=>'something'在我的应用程序中,我在路由文件中有以下内容match'profile'=>'User#show'我的表演Action是这样的defshow@user=User.find(params[:user])@title=@user.first_nameend重定向发生在同一个用户Controller中,就像这样defregister@title="Registration"@user=Use

  5. ruby - 使用 `+=` 和 `send` 方法 - 2

    如何将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.你能做的最好的事情是:

  6. ruby-on-rails - 从应用程序中自定义文件夹内的命名空间自动加载 - 2

    我们目前正在为ROR3.2开发自定义cms引擎。在这个过程中,我们希望成为我们的rails应用程序中的一等公民的几个类类型起源,这意味着它们应该驻留在应用程序的app文件夹下,它是插件。目前我们有以下类型:数据源数据类型查看我在app文件夹下创建了多个目录来保存这些:应用/数据源应用/数据类型应用/View更多类型将随之而来,我有点担心应用程序文件夹被这么多目录污染。因此,我想将它们移动到一个子目录/模块中,该子目录/模块包含cms定义的所有类型。所有类都应位于MyCms命名空间内,目录布局应如下所示:应用程序/my_cms/data_source应用程序/my_cms/data_ty

  7. ruby-on-rails - Rails - 从命名路由中提取 HTTP 动词 - 2

    Rails中有没有一种方法可以提取与路由关联的HTTP动词?例如,给定这样的路线:将“users”匹配到:“users#show”,通过:[:get,:post]我能实现这样的目标吗?users_path.respond_to?(:get)(显然#respond_to不是正确的方法)我最接近的是通过执行以下操作,但它似乎并不令人满意。Rails.application.routes.routes.named_routes["users"].constraints[:request_method]#=>/^GET$/对于上下文,我有一个设置cookie然后执行redirect_to:ba

  8. ruby - 如何计算 Liquid 中的变量 +1 - 2

    我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我

  9. ruby - Chef LW 资源属性默认值如何引用另一个属性? - 2

    我正在尝试将一个资源属性的默认值设置为另一个属性的值。我正在为我正在构建的tomcat说明书定义一个资源,其中包含以下定义。我想要可以独立设置的“名称”和“服务名称”属性。当未设置服务名称时,我希望它默认为为“名称”提供的任何内容。以下不符合我的预期:attribute:name,:kind_of=>String,:required=>true,:name_attribute=>trueattribute:service_name,:kind_of=>String,:default=>:name注意第二行末尾的“:default=>:name”。当我在Recipe的新block中引用我

  10. arrays - Ruby 数组 += vs 推送 - 2

    我有一个数组数组,想将元素附加到子数组。+=做我想做的,但我想了解为什么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”]、[“苹果”、“

随机推荐