我第一次使用地图,我意识到有很多方法可以插入元素.您可以使用emplace(),operator[]或者insert()使用value_type或使用或等变体make_pair.虽然有很多关于所有这些信息以及有关特定案例的问题的信息,但我仍然无法理解大局.所以,我的两个问题是:
每个人比其他人的优势是什么?
是否需要在标准中添加安全性?没有它之前有什么是不可能的吗?
在C++中,11 emplace_back()通常是优选的(在效率方面),push_back()因为它允许就地构造,但是当使用push_back(std::move())已经构造的对象时仍然是这种情况吗?
例如,emplace_back()在以下情况下仍然是首选?
std::string mystring("hello world");
std::vector<std::string> myvector;
myvector.emplace_back(mystring);
myvector.push_back(std::move(mystring));
// (of course assuming we don't care about using the value of mystring after)
Run Code Online (Sandbox Code Playgroud)
另外,在上面的例子中有没有任何好处来代替:
myvector.emplace_back(std::move(mystring));
Run Code Online (Sandbox Code Playgroud)
或者这里的举动完全是多余的,还是没有效果?
C++ 11 std::map<K,V>类型具有一个emplace函数,许多其他容器也是如此.
std::map<int,std::string> m;
std::string val {"hello"};
m.emplace(1, val);
Run Code Online (Sandbox Code Playgroud)
此代码的工作方式与宣传的一样,std::pair<K,V>直接安排,但它会产生副本key并val发生.
是否可以将值类型直接置于地图中?我们能比调用中的参数更好emplace吗?
这是一个更彻底的例子:
struct Foo
{
Foo(double d, string s) {}
Foo(const Foo&) = delete;
Foo(Foo&&) = delete;
}
map<int,Foo> m;
m.emplace(1, 2.3, string("hello")); // invalid
Run Code Online (Sandbox Code Playgroud) emplace_back做以下事情时,我认为这将是胜利者:
v.push_back(myClass(arg1, arg2));
Run Code Online (Sandbox Code Playgroud)
因为emplace_back会在向量中立即构造对象,而push_back首先会构造一个匿名对象,然后将其复制到向量中.有关更多信息,请参阅此问
我决定将它们与一个由整数填充的向量进行比较.
这是实验代码:
#include <iostream>
#include <vector>
#include <ctime>
#include <ratio>
#include <chrono>
using namespace std;
using namespace std::chrono;
int main() {
vector<int> v1;
const size_t N = 100000000;
high_resolution_clock::time_point t1 = high_resolution_clock::now();
for(size_t i = 0; i < N; ++i)
v1.push_back(i);
high_resolution_clock::time_point t2 = high_resolution_clock::now();
duration<double> time_span = duration_cast<duration<double>>(t2 - t1);
std::cout << "push_back took me " << time_span.count() << " seconds.";
std::cout << …Run Code Online (Sandbox Code Playgroud) 以下代码不会在gcc 4.8.2上编译.问题是此代码将尝试复制构造,std::pair<int, A>这是由于struct A缺少复制和移动构造函数而无法发生的.
gcc在这里失败了还是我错过了什么?
#include <map>
struct A
{
int bla;
A(int blub):bla(blub){}
A(A&&) = delete;
A(const A&) = delete;
A& operator=(A&&) = delete;
A& operator=(const A&) = delete;
};
int main()
{
std::map<int, A> map;
map.emplace(1, 2); // doesn't work
map.emplace(std::piecewise_construct,
std::forward_as_tuple(1),
std::forward_as_tuple(2)
); // works like a charm
return 0;
}
Run Code Online (Sandbox Code Playgroud) 考虑以下:
std::vector<std::unique_ptr<int>> ptrsToInts;
ptrsToInts.emplace_back(new int);
Run Code Online (Sandbox Code Playgroud)
如果在向量中发生重新分配,并且失败(抛出std::bad_alloc),我是"安全"还是会泄漏int?
C++ 11 23.3.6.5 [vector.modifiers]/1说:
如果除了复制构造函数之外抛出异常,则移动构造函数,赋值运算符或移动赋值运算符
T或通过任何InputIterator运算都没有效果.
这似乎表明这是一个潜在的问题.也就是说,如果存在"无效果",则unique_ptr从未构造过,因此delete不会发生依赖于该指针的析构函数行为.(这可能表明emplace_back应该禁止容器的unique_ptrs)
我有一个类型,我已经删除了复制构造函数,我想有一个vector这种类型,所以我需要通过创建所有元素emplace_back.但是,emplace_back似乎需要一个复制构造函数,因为编译器会发出一个关于无法实例化的警告,emplace_back因为复制构造函数已被删除.为什么需要复制构造函数?我认为重点emplace_back是建立vector没有复制任何东西.我甚至可以拥有一个vector没有复制构造函数的对象吗?
class MyType {
public:
MyType(std::array<double, 6> a) {}
MyType(const MyType& that) = delete;
};
int main() {
std::vector<MyType> v;
std::array<double, 6> a = {1,2,3,4,5,6};
v.emplace_back(a);
}
Run Code Online (Sandbox Code Playgroud)
编译器是clang/llvm.
我刚学会了C++ 17中保证的复制省略.根据该问题的答案:
执行
return T();此操作时,将通过a初始化函数的返回值prvalue.由于该函数返回T,因此不会创建临时函数;prvalue简单的初始化直接初始化返回值.要理解的是,由于返回值是a
prvalue,它还不是一个对象.它只是一个对象的初始化器,就像T()是.
所以我想知道,这是否适用于除以下之外的任何事情:
T f() {return T();}
T t = f();
Run Code Online (Sandbox Code Playgroud)
所以我编写了这段代码emplace_back来测试它:
#include <vector>
#include <iostream>
struct BigObj{
BigObj() = default;
BigObj(int) { std::cout << "int ctor called" << std::endl; }
BigObj(const BigObj&){
std::cout << "copy ctor called" << std::endl;
}
BigObj(BigObj&&){
std::cout << "move ctor called" << std::endl;
}
};
BigObj f(){ return BigObj(2); }
int g(){ return 2; }
int main(){ …Run Code Online (Sandbox Code Playgroud) 我有一个,std::vector<std::vector<double>>并希望在它的末尾添加一些元素,所以这是我的试用:
std::vector<std::vector<double> > vec;
vec.emplace_back({0,0});
Run Code Online (Sandbox Code Playgroud)
但这不会编译,而以下将执行:
std::vector<double> vector({0,0});
Run Code Online (Sandbox Code Playgroud)
为什么emplace_back不能在这个位置构造元素?或者我做错了什么?
谢谢你的帮助.
我有一个类,其副本构造函数被显式删除(因为A在内部使用指针,我不想陷入浅层复制陷阱):
class A {
public:
A(const A&) = delete;
A& operator=(const A&) = delete;
A(const B& b, const C& c);
}
Run Code Online (Sandbox Code Playgroud)
现在我有一个类型的向量,vector<A> aVector;我想在其中插入元素 - 所以我使用emplace_back:
aVector.emplace_back(b, c);
Run Code Online (Sandbox Code Playgroud)
但是,这无法使用gcc编译,我收到错误 -
third-party/gcc-4.7.1-glibc-2.14.1/libgcc/libgcc-4.7.1/afc21dc/include/c++/4.7.1/bits/stl_construct.h: In instantiation of 'void std::_Construct(_T1*, _Args&& ...)
third-party/gcc-4.7.1-glibc-2.14.1/libgcc/libgcc-4.7.1/afc21dc/include/c++/4.7.1/bits/stl_uninitialized.h:77:3: required from 'static _ForwardIterator std::__uninitialized_copy<_TrivialValueTypes>::__uninit_copy(_InputIterator, _InputIterator, _ForwardIterator)
third-party/gcc-4.7.1-glibc-2.14.1/libgcc/libgcc-4.7.1/afc21dc/include/c++/4.7.1/bits/stl_uninitialized.h:119:41: required from '_ForwardIterator std::uninitialized_copy(_InputIterator, _InputIterator, _ForwardIterator)
third-party/gcc-4.7.1-glibc-2.14.1/libgcc/libgcc-4.7.1/afc21dc/include/c++/4.7.1/bits/stl_uninitialized.h:260:63: required from '_ForwardIterator std::__uninitialized_copy_a(_InputIterator, _InputIterator, _ForwardIterator, std::allocator<_Tp>&)
third-party/gcc-4.7.1-glibc-2.14.1/libgcc/libgcc-4.7.1/afc21dc/include/c++/4.7.1/bits/stl_uninitialized.h:283:67: required from '_ForwardIterator std::__uninitialized_move_if_noexcept_a(_InputIterator, _InputIterator, _ForwardIterator, _Allocator&)
third-party/gcc-4.7.1-glibc-2.14.1/libgcc/libgcc-4.7.1/afc21dc/include/c++/4.7.1/bits/vector.tcc:410:6: required from 'void std::vector<_Tp, _Alloc>::_M_emplace_back_aux(_Args&& ...)
third-party/gcc-4.7.1-glibc-2.14.1/libgcc/libgcc-4.7.1/afc21dc/include/c++/4.7.1/bits/vector.tcc:102:4: …Run Code Online (Sandbox Code Playgroud) emplace ×10
c++ ×9
c++11 ×5
dictionary ×2
push-back ×2
stl ×2
c++17 ×1
constructor ×1
insert ×1
map ×1
operators ×1
performance ×1
std-pair ×1
stdvector ×1
vector ×1