这个问题已经在这里有了答案:
std::vector<int> a;
std::vector<int> b;
std::vector<int> c;
我想通过将std::move
和C++11
的元素添加到a
来串联这三个向量,这是最好的方法,为什么?
1)使用std::move
:
a.reserve(a.size() + b.size() + c.size());
a.insert(a.end(), b.begin(), b.end());
a.insert(a.end(), c.begin(), c.end());
b.clear();
c.clear();
2)使用std::move
:
a.reserve(a.size() + b.size() + c.size());
std::copy(b.begin(), b.end(), std::inserter(a, a.end()));
std::copy(c.begin(), c.end(), std::inserter(a, a.end()));
b.clear();
c.clear();
3)使用std::move
(来自C++11
):
a.reserve(a.size() + b.size() + c.size());
std::move(b.begin(), b.end(), std::inserter(a, a.end()));
std::move(c.begin(), c.end(), std::inserter(a, a.end()));
b.clear();
c.clear();
我读过
“多个线程可以同时读写不同的 shared_ptr对象,即使对象是共享的副本 所有权。”(MSDN:标准C ++库中的线程安全)
这是否意味着更改shared_ptr对象是安全的?
例如,下一个代码是否被认为是安全的:
shared_ptr<myClass> global = make_shared<myClass>();
...
//In thread 1
shared_ptr<myClass> private = global;
...
//In thread 2
global = make_shared<myClass>();
...
在那种情况下,我可以确定线程1 global
的原始值是thread 1
还是线程2分配的新值,但是无论哪种方式,它都将对myClass有效的shared_ptr?
==编辑==
只是为了解释我的动机。 我想要一个共享的指针来保存我的配置,并且我有一个线程池来处理请求。
因此global
是全局配置。thread 1
在开始处理请求时采用了当前配置。thread 2
正在更新配置。 (仅适用于将来的请求)
如果可行,我可以用这种方式更新配置,而不必在请求处理过程中破坏配置。
我想做什么:我想对锁定在一起的2个,3个或N个向量进行排序,而无需将它们复制到元组中。 也就是说,将冗长性放在一边,类似:
vector<int> v1 = { 1, 2, 3, 4, 5};
vector<double> v2 = { 11, 22, 33, 44, 55};
vector<long> v3 = {111, 222, 333, 444, 555};
typedef tuple<int&,double&,long&> tup_t;
sort(zip(v1,v2,v3),[](tup_t t1, tup_t t2){ return t1.get<0>() > t2.get<0>(); });
for(auto& t : zip(v1,v2,v3))
cout << t.get<0>() << " " << t.get<1>() << " " << t.get<2>() << endl;
这应该输出:
5 55 555
4 44 444
...
1 11 111
我现在的操作方式:我实现了自己的quicksort,其中我传递的第一个数组用于比较,并且排列应用于所有其他数组。 我只是想不通如何针对我的问题重用std :: sort(例如提取排列)。
我尝试了什么:boost :: zip_iterator和boost :: zip_range(带有boost :: combine range),但是std :: sort和boost :: range :: algorithm :: sort都抱怨迭代器/范围是只读的 而不是随机访问...
问题:如何在锁定步骤(压缩)中对N个向量进行排序? 这个问题看起来很普通而且很常见,所以我想必须通过一个可能非常复杂的库来找到一个简单的解决方案,但是我找不到它...
备注:是的,stackoverflow中也有类似的问题,这个问题经常以不同的形式被问到。 但是,它们始终使用以下答案之一关闭:
提示:
根本的问题是数组引用的“成对”的行为不像它们应该表现的那样,我只是决定滥用迭代器的符号并编写有效的东西。 这涉及有效地编写一个不一致的迭代器,其中值类型的引用与引用类型不同。
答:请参阅下面的“ interjay评论”(这也会部分回答未来的问题):
#include "tupleit.hh"
#include <vector>
#include <iostream>
#include <boost/range.hpp>
#include <boost/range/algorithm/sort.hpp>
#include <boost/range/algorithm/for_each.hpp>
template <typename... T>
auto zip(T&... containers)
-> boost::iterator_range<decltype(iterators::makeTupleIterator(std::begin(containers)...))> {
return boost::make_iterator_range(iterators::makeTupleIterator(std::begin(containers)...),
iterators::makeTupleIterator(std::end(containers)...));
}
int main() {
typedef boost::tuple<int&,double&,long&> tup_t;
std::vector<int> a = { 1, 2, 3, 4 };
std::vector<double> b = { 11, 22, 33, 44 };
std::vector<long> c = { 111, 222, 333, 444 };
auto print = [](tup_t t){ std::cout << t.get<0>() << " " << t.get<1>() << " " << t.get<2>() << std::endl; };
boost::for_each( zip(a, b, c), print);
boost::sort( zip(a, b, c), [](tup_t i, tup_t j){ return i.get<0>() > j.get<0>(); });
for ( auto tup : zip(a, b, c) ) print(tup);
return 0;
}
未来的问题:先前的答案适用于序列容器。 我们还能在可排序的容器(例如序列和列表)上使用它吗? 这将需要random_access和双向TupleIterators,以及在双向迭代器上工作的排序算法。
更新:这适用于类似序列的容器的组合。 但是,混合列表将需要std :: sort支持BidirectionalIterators(不需要)。
我想使用BOOST_FOREACH遍历std :: map并编辑值。 我不太明白。
typedef std::pair<int, int> IdSizePair_t;
std::map<int,int> mmap;
mmap[1] = 1;
mmap[2] = 2;
mmap[3] = 3;
BOOST_FOREACH( IdSizePair_t i, mmap )
i.second++;
// mmap should contain {2,3,4} here
当然,这不会改变任何东西,因为我没有通过引用进行迭代。 因此,我改为用这行代替(按照Boost文档中的示例):
BOOST_FOREACH( IdSizePair_t &i, mmap )
我得到编译器错误:
error C2440: 'initializing' :
cannot convert from 'std::pair<_Ty1,_Ty2>' to 'IdSizePair_t &'
with
[
_Ty1=const int,
_Ty2=int
]
有什么建议?
我想知道是否要复制向量,是否要复制具有其值的向量(而这不适用于数组,而深度复制需要循环或memcpy)。
你能暗示一个解释吗?
问候
是否有规则说明std :: tuple的成员按什么顺序销毁?
例如,如果Function1
返回std::tuple<std::unique_ptr<ClassA>, std::unique_ptr<ClassB>>
到Function2
,那么我可以确定(当保留Function2
的范围时)第二个成员引用的ClassB
实例在第一个成员引用的ClassA
实例之前被销毁了吗?
std::tuple< std::unique_ptr< ClassA >, std::unique_ptr< ClassB > > Function1()
{
std::tuple< std::unique_ptr< ClassA >, std::unique_ptr< ClassB > > garbage;
get<0>(garbage).reset( /* ... */ );
get<1>(garbage).reset( /* ... */ );
return garbage;
}
void Function2()
{
auto to_be_destroyed = Function1();
// ... do something else
// to_be_destroyed leaves scope
// Is the instance of ClassB destroyed before the instance of ClassA?
}
使用gcc进行编译时,何时需要对编译器和链接器使用标志-std=c++11
?
编译器会自动使用libstdc ++吗?
我在Ubuntu 13.10上使用gcc4.8.2,我想使用c ++ 11标准。 我已经将-std=c++11
传递给了编译器。
编写C ++代码时,两者之间有什么区别:
#include <cstdlib>
和
#include <stdlib.h>
除了前者主要包含在std::
命名空间中?
除了编码标准和样式之外,是否还有其他理由要使用一种?
让我首先解释“魔术”的含义。 我将使用Java中的两个示例:
Object
类。String
对象定义了Object
运算符。这意味着不可能在pure(*)Java中实现Object
和String
类的实现。 现在,这就是我所说的“魔术”的含义:要实现这些类,您将需要编译器的一些特殊支持。
就我所知,我一直喜欢C ++的地方是,据我所知,STL中没有发生这种“魔术”现象,即可以在纯C ++中实现STL。
现在我的问题是:这是真的吗? 还是STL的某些部分无法在纯C ++中实现,并且需要一些“魔术” /特殊编译器支持?
(*)“纯”是指不使用任何类库。
我正在使用android NDK r9d和工具链4.8,但无法使用std :: to_string函数,编译器会引发以下错误:
error: 'to_string' is not a member of 'std'
android ndk不支持此功能吗? 我尝试APP_CPPFLAGS := -std=c++11
没有运气。
可能重复:
为什么“使用命名空间标准”; 在C ++中被认为是不好的做法?
使用标准命名空间
香港专业教育学院一直徘徊在许多不同的论坛,我似乎看到这一次又一次弹出。 这是一个非常初学者的问题。
我通常用
#include<string>
using namespace std;
string x;
我看到有一堆定义字符串为的代码示例
std::string.
这样做的目的是什么? 是好的做法还是有一些功能?
考虑我有一个自定义类型(可以扩展):
struct Foo {
int a;
string b;
};
如何使该对象的实例可分配给operator =
,即tuple<int&,string&> = Foo
引用?
Foo foo = ...;
int a;
string b;
std::tie(a, b) = foo;
尝试失败:
无法重载operator =
的赋值运算符,因为赋值运算符是二进制运算符之一,必须是左侧对象的成员。
因此,我尝试通过实现合适的元组转换运算符来解决此问题。 以下版本失败:
operator =
operator =
它们导致分配时出错,并告知“ tuple<int&,string&> = Foo
没有过载tuple<int&,string&> = Foo
”。 我猜这是因为“转换为任何类型X +推导operator =“的模板参数X不能一起工作,只能一次进行。
不完美的尝试:
因此,我尝试为领带的确切类型实现一个转换运算符:
tie
演示tie
Demo分配现在可以工作了,因为类型现在(转换后)完全相同,但是这在我要支持的三种情况下不起作用:
tie
更改为std::tie
),则由于类型必须完全匹配而失败。 这与将元组分配给允许可转换类型的引用元组的通常用法相矛盾。(1)tie
的分配也会失败。 要实现const版本的转换,我们需要破解const主题成员的constness。 这很丑陋,可能会被滥用,从而导致不确定的行为。我只看到一种替代方法,即提供自己的tie
函数+类以及“可绑定”对象,这使我不得不复制我不喜欢的std::tie
的功能(并不是我很难做到, 但必须这样做是不对的)。
我认为最终结论是,这是仅库元组实现的一个缺点。 它们不像我们希望的那样神奇。
事实证明,似乎没有解决上述所有问题的真正解决方案。 一个很好的答案可以解释为什么这不能解决。 特别是,我希望有人阐明为什么“失败的尝试”可能行不通。
(1):一个可怕的技巧是将转换作为模板编写,并在转换运算符中转换为请求的成员类型。 这是一个可怕的骇客,因为我不知道将这些转换后的成员存储在哪里。 在此演示中,我使用静态变量,但这不是线程可重入的。
(2):可以应用与(1)中相同的技巧。
为什么ctime()
返回的字符串的最后一个字符是换行符(0x0A
)? 例如,此代码:
#include <iostream>
#include <cstdlib>
int main(int argc, char* argv[])
{
time_t now;
time(&now);
char* time_str = ctime(&now);
std::cout << time_str << "why is this on a new line?" << std::endl;
return 0;
}
...产生以下输出:
$ ./time.exe
Wed Oct 23 14:52:29 2013
why is this on a new line?
$
没什么大不了的; 我可以从字符串中删除最后一个字节,但是为什么ctime()
却将它放在首位呢?
我了解为什么不能做到这一点的原因(重新平衡和填充):
iterator i = m.find(33);
if (i != m.end())
i->first = 22;
但是到目前为止(我知道)更改键的唯一方法是将所有节点从树上一起删除,然后使用另一个键将值插入回去:
iterator i = m.find(33);
if (i != m.end())
{
value = i->second;
m.erase(i);
m[22] = value;
}
由于更多原因,这对我来说似乎效率很低:
我发现这三个分配和释放最差。 我是否缺少某些东西,或者有更有效的方法吗?
更新:我认为从理论上讲应该有可能,因此我认为更改其他数据结构是没有道理的。 这是我想到的伪算法:
如何将std::chrono::time_point
转换为带有小数秒的日历日期时间字符串?
例如:
"10-10-2012 12:38:40.123456"
我有一个正在对某些图像执行某些处理的应用程序。
假定我知道宽度/高度/格式等(我知道),然后考虑定义一个缓冲区来存储像素数据:
然后,我正在考虑使用std::vector
来简化事情,而不是在unsigned char*
上使用memcpy_s
和resize
并单独记录缓冲区大小。
所以我要声明我的班级是这样的:
#include <vector>
class MyClass
{
// ... etc. ...
public:
virtual void OnImageReceived(unsigned char *pPixels,
unsigned int uPixelCount);
private:
std::vector<unsigned char> m_pImageBuffer; // buffer for 8-bit pixels
// ... etc. ...
};
然后,当我收到一张新的图像(具有可变大小-但不用担心这里的细节)时,我可以调整矢量的大小(如有必要)并复制像素:
void MyClass::OnImageReceived(unsigned char *pPixels, unsigned int uPixelCount)
{
// called when a new image is available
if (m_pImageBuffer.size() != uPixelCount)
{
// resize image buffer
m_pImageBuffer.reserve(uPixelCount);
m_pImageBuffer.resize(uPixelCount, 0);
}
// copy frame to local buffer
memcpy_s(&m_pImageBuffer[0], m_pImageBuffer.size(), pPixels, uPixelCount);
// ... process image etc. ...
}
这对我来说似乎很好,我喜欢我不必担心内存管理的事实,但这引起了一些问题:
memcpy_s
的有效申请,还是有一个更合适的容器?memcpy_s
和resize
做正确的事情?memcpy_s
吗?任何其他评论,批评或建议都将受到欢迎。
从vector<string>
获得键和值的列表(作为unordered_map<string, double>
)的最有效方法是什么?
为了具体起见,假设所讨论的地图是unordered_map<string, double>
。然后,我想以vector<string>
的形式获取密钥,以vector<double>
的形式获取值。
unordered_map<string, double> um;
vector<string> vs = um.enum_keys();
vector<double> vd = um.enum_values();
我可以遍历地图并收集结果,但是还有更多内容吗?有效的方法? 有一种也可以用于常规地图的方法会很好,因为我可能会切换到那个。
我正在尝试通过捕获移动的lambda表达式创建std::unique_ptr<int>
。 请注意,我可以毫无问题地创建一个移动捕获的lambda表达式; 只有当我尝试将其包装在on_mouse_down()
中时,才会出现错误。
例如:
auto pi = std::make_unique<int>(0);
// no problems here!
auto foo = [q = std::move(pi)] {
*q = 5;
std::cout << *q << std::endl;
};
// All of the attempts below yield:
// "Call to implicitly-deleted copy constructor of '<lambda...."
std::function<void()> bar = foo;
std::function<void()> bar{foo};
std::function<void()> bar{std::move(foo)};
std::function<void()> bar = std::move(foo);
std::function<void()> bar{std::forward<std::function<void()>>(foo)};
std::function<void()> bar = std::forward<std::function<void()>>(foo);
我将解释为什么我要写这样的东西。 我已经编写了一个UI库,类似于jQuery或JavaFX,它允许用户通过将std::unique_ptr<int>
s传递给名称为on_mouse_down()
、on_mouse_drag()
、push_undo_action()
等的方法来处理鼠标/键盘事件。
显然,我希望传递的std::unique_ptr<int>
最好使用移动捕获的lambda表达式,否则我需要诉诸在C ++ 11为标准时使用的难看的“ release / acquire-in-lambda”习惯用法:
std::function<void()> baz = [q = pi.release()] {
std::unique_ptr<int> p{q};
*p = 5;
std::cout << *q << std::endl;
};
请注意,两次调用std::unique_ptr<int>
在上面的代码中将是错误。 但是,在我的代码中,此闭包被保证只被调用一次。
顺便说一句,在我的真实代码中,我没有传递std::unique_ptr<int>
,但是更有趣。
最后,我正在使用Xcode6-Beta4,它使用以下版本的clang:
Apple LLVM version 5.1 (clang-503.0.40) (based on LLVM 3.4svn)
Target: x86_64-apple-darwin13.3.0
Thread model: posix
我很想知道std :: string是如何实现的,它与c字符串有什么不同?如果标准未指定任何实现,那么任何带有解释的实现都将很好地满足标准给出的字符串要求?
我需要按值而不是键对std::map
进行排序。 有一个简单的方法吗?
我从以下线程获得了一种解决方案:
std :: map按数据排序?
有更好的解决方案吗?
map<long, double> testMap;
// some code to generate the values in the map.
sort(testMap.begin(), testMap.end()); // is there any function like this to sort the map?