- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我正在使用以下代码测试通用引用,
template <typename T>
vector<T> attach_(vector<T> xs, T&& x) {
xs.push_back(std::forward<T>(x));
return xs;
}
int main() {
int k = 2;
attach_(std::move(vector<int>{1,2,3}),k); //not OK
attach_(std::move(vector<int>{1,2,3}),(int&)k); //not OK
attach_(std::move(vector<int>{1,2,3}),(int)k); //OK
attach_(std::move(vector<int>{1,2,3}),2); //OK
}
出现错误:
no matching function for call to 'attach_(std::remove_reference<std::vector<int> >::type, int&)'
attach_(std::move(vector<int>{1,2,3}),k);
note: template argument deduction/substitution failed:
note: deduced conflicting types for parameter 'T' ('int' and 'int&')
attach_(std::move(vector<int>{1,2,3}),k);
SO 有一个类似错误的问题 Error message "deduced conflicting types for parameter 'const T'"关于 const 引用。
我还测试了其他一些案例,其中一些案例进行了类型转换。有些有效,有些则无效。
我听说像 T&&
这样的通用引用可以匹配所有内容。为什么这里失败了?
第二个问题是,如何键入 attach_
以确保移动语义对 xs
和 x
都有效以进行适当的输入?最后,我想要以下变体:
for(int i = 0; i < 100; i++)
xs = attach_(xs,values[i])
工作时不要制作不必要的拷贝。
(这是用gcc4.8.1测试的,使用g++ -std=c++11 test.cpp)
谢谢
-- 编辑 ---
感谢大家的精彩回答。
所以我现在明白了,对于这种情况,使用按值传递并移动 T
是很有效的。如果在循环中使用, vector xs 不会在参数传递和返回过程中被不必要地复制,对吗?
我问了一个相关问题When is a const reference better than pass-by-value in C++11? .在那里,我有这个例子,每个人都说 pass-by-vale 是个坏主意:
int hd(vector<int> a) {
return a[0];
}
是否可以使用通用引用来处理这篇文章中的 hd
情况和 attach_
情况以避免不必要的复制?
再次感谢。
--- 编辑2 ---
因此,我测试了答案中的版本以及下面的 const
引用版本。优化不用于暴露任何潜在问题。 const
ref 版本是最差的,因为它强制复制。如果将 std::move(a)
用于 vector ,则其他一切都具有相同的速度,除了原始 push_call
调用更快。我想优化可以消除这种差异。我想测试(或者可能是 int 类型)不够大,无法显示 push_back(x)
和 push_back(std::move(x))
#include <vector>
#include <iostream>
#include <chrono>
using namespace std;
template <class T>
vector<T> attach(vector<T> v, T x) {
v.push_back(x);
return v;
}
template <typename T>
vector<T> attach1(vector<T> xs, T x) {
xs.push_back(std::move(x));
return xs;
}
template <typename T, typename E = typename std::remove_reference<T>::type>
std::vector<E> attach2(std::vector<E> xs, T&& x) {
xs.push_back(std::forward<T>(x));
return xs;
}
template <typename C, typename T> C attach3(C&& xs, T&& x) {
xs.push_back(std::move<T>(x));
return std::forward<C>(xs);
}
template <class T>
vector<T> attach4(const vector<T>& v, T x) {
vector<T> ret = v;
ret.push_back(x);
return std::move(ret);
}
using namespace std::chrono;
int main() {
int N = 100000;
vector<int> a;
auto time = high_resolution_clock::now();
for (int i = 0; i < N; i++) {
//a.push_back(i); //0s
//a = attach(a,i); //15s
//a = attach(std::move(a),i); //0.03s
//a = attach2(std::move(a),i); //0.03s
a = attach3(std::move(a),i); //0.03s
//a = attach4(std::move(a),i); //14.9s
}
cout << duration_cast<duration<double>>(high_resolution_clock::now() - time).count() << endl;
}
最佳答案
通用引用的工作方式是这样的:如果你传入一个右值,那么 T
将被推断为 int
(或其他一些非引用类型),因为那时 T&&
是右值引用类型。但是如果你传入一个左值,那么T
将被推断为 int&
(或其他一些左值引用类型),因为那时 T&&
将是左值引用类型(因为左值引用和右值引用“折叠”在一起成为左值引用)。
所以在你传递一个左值的情况下,你有一个问题,因为你不能有 vector<T>
什么时候T
是引用类型。
你应该只按值传递,
template <typename T>
std::vector<T> attach_(std::vector<T> xs, T x) {
xs.push_back(std::move(x));
return xs;
}
这可能看起来效率较低,但事实并非如此。如果你传入一个右值,它将被移动一次到 x
中, 并再次移动到 vector 中。如果你传入一个左值,它将被复制一次到 x
中, 他们移动到 vector 中。这与通过引用传递相同:左值一个拷贝,右值零个拷贝。
出于教育目的,您可以使用通用引用来做到这一点:
template <typename T, typename E = typename std::remove_reference<T>::type>
std::vector<E> attach_(std::vector<E> xs, T&& x) {
xs.push_back(std::forward<T>(x));
return xs;
}
这确保当您传递一个左值时, vector 元素类型是非引用类型。但按值传递确实更好。
关于c++ - 推断出参数 'T' 的冲突类型以供通用引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24621954/
大家好我有一个应用程序可以打开一个包含文本和图像组合的文章的 WebView 。如您所知,文章有不同的字体,我想知道是否有办法让 Web View 呈现几种 Helvetica 字体,就像在安装了这些
我正在寻找一种好的格式来归档旧 Linux 计算机的整个文件系统。 西藏自治区 tar.gz 格式非常适合归档具有 UNIX 样式属性的文件,但由于压缩应用于整个归档,因此设计排除了随机访问。相反,如
我最近一直在苦苦挣扎,因为我不得不更改我不久前编写的一些代码以在 Qt 中进行图像处理和 OpenGl以支持多线程。 问题是我想用它在一组图像上应用批量过滤器, 我正在使用 openMP 来做这样的多
我已成功将两个实际设备连接到 Azure IoTHub(在同一个 IoT 中心),并希望第二个设备接收第一个设备发送的消息。因此,在普通的 MQTT 代理中,第二个设备仅订阅该主题,但 Azure没有
我需要一些 Jenkins 作业才能通过 ssh 通过 shell 命令行访问其他一些机器。 我该怎么做? 我没有目标服务器的密码,但我有一个“ key ”文件,但是当我使用以下命令运行作业时 ssh
我在 Mac OSX Mavericks 上使用 MAMP。我想安装最新的 XDebug v2.2.4。根据 XDebug 向导,我下载了 XDebug 2.2.4 源代码。我的系统上安装了许多版本的
所以我正在制作一个程序,从用户给定的 AZ Lyrics 歌曲中提取歌词。我遇到的问题是,在将字符串转换为 URL 后,它说 Jsoup 无法解析它,因为它不接受字符串,尽管变量是我们传入的 URL。
我已经安装了 AWS .NET SDK通过 MSI 安装程序。我想使用这段代码: static IAmazonS3 client; client = new AmazonS3Client(Amazon
我正在使用 cURL 检索另一个页面,除非我有特定的 cookie,否则我看不到页面内容。 cookie 名称是 seepage,它的值必须设置为 1 才能让我看到页面内容。 我想使用 cURL 加载
目录 1、VLC代码封装 1.1 QT(C++)工程 1.2static 声明 m_instance 优化效率 1.3封装 DLL
我是 Docker 新手,但有一个 Java Web 应用程序项目,我的 Maven 构建会为其生成并安装 Docker 镜像。即 mvn clean install 产品: REPOSITORY
我正在尝试在 Debian Stretch 上做一个带有 uinput 的虚拟键盘,我可以输入字符串,比如“Toto!”,键盘会写入这个字符串。但是,我一直坚持从 C char 到键盘处理的键码的转换
我们正在 Rails 中开发一个 JSON REST API,供我们也在开发的 Android 应用程序使用。有什么方法可以保护 API,使其只能由我们特定的 Android 应用程序使用? API
关闭。这个问题需要debugging details .它目前不接受答案。 编辑问题以包含 desired behavior, a specific problem or error, and th
所以我有一个问题,我有 2 个应用程序部署在具有不同端口的同一网站上,一个是登录应用程序,一个是HRIS 系统。 我的问题是,当我的登录应用程序创建 token 时并重定向到我的 hris 系统,hr
在给出的第三段代码的上下文中交谈 on this page , 有一个方法 Messenger named getBinder()返回 the IBinder Messenger 用于与 associ
我目前有一个私有(private) Java 项目,我正在尝试将其完善以供其他开发人员使用。我想做的一件事是让 Ant 自己下载 JUnit、PMD 和 FindBugs 等所需的 JAR,这样开发人
我想在 Qt 中使用 ffmpeg 库进行编程。 如何在 Windows 上将 ffmpeg 编译成 *.lib 文件? 或 如何使用Qt官方发布的编译后的*.dll文件? 还有,哪种方式比较好? 最
我正在为扩展 std::vector 实例化的 C++ 类开发 Python 绑定(bind)。为了让 Python 下标运算符为此类工作,我添加了如下所示的 __getitem__ 函数(我删除了不
我正在为 Amazon SWF 的相当简单的工作流程编写 PHP。我发现自己开始编写一个库来检查某些操作是否已经开始或完成。基本上遍历事件列表以检查事情的进展情况,然后在需要时启动适当的事件。有时这可
我是一名优秀的程序员,十分优秀!