3 回答
TA贡献1874条经验 获得超12个赞
因此,实际上,在调用resize()时,通过添加适当数量的val副本来扩大向量。但是,通常,我只需要知道向量足够大即可容纳我需要的数据。我不需要将其初始化为任何值。复制构造新值只是浪费时间。
不,不是。拥有实际上没有构造的元素的容器是没有意义的。我不确定您希望看到的不是零。未指定/未初始化的元素?这不是价值初始化的意思。
如果您需要N个元素,那么您应该有N个正确构造的元素,这就是需要的std::vector::resize。值初始化将使对象初始化为零,而没有默认构造函数可调用,因此,实际上这与您想要的相反,安全性和初始化程度较低,而不是更多。
我建议你真正想要的是std::vector::reserve。
这似乎表明std::vector<T>界面更改并未真正起任何作用
它肯定会产生作用,但不是您要寻找的那个。新的resize重载是为了方便起见,因此当您只需要默认或什至值初始化时,您就不必构造自己的临时文件。这不是容器工作方式的根本变化,而是它们始终持有有效的†类型的†实例。
†有效,但如果您离开它们,则处于未指定状态!
TA贡献1884条经验 获得超4个赞
还有就是用C ++ 11个小功能上的差异resize签名,但您的测试不会揭露它。考虑类似的测试:
#include <iostream>
#include <vector>
struct X
{
X() {std::cout << "X()\n";}
X(const X&) {std::cout << "X(const X&)\n";}
};
int
main()
{
std::vector<X> v;
v.resize(5);
}
在C ++ 03下打印:
X()
X(const X&)
X(const X&)
X(const X&)
X(const X&)
X(const X&)
但是在C ++ 11下它会打印:
X()
X()
X()
X()
X()
进行此更改的动机是为了更好地支持中的不可复制(仅移动)类型vector。在大多数情况下,包括您的情况在内,此更改都没有影响。
有一种方法可以通过使用自定义分配器(您的编译器可能支持或可能不支持)来完成C ++ 11中的目标:
#include <iostream>
#include <vector>
using namespace std;
template <class T>
class no_init_alloc
: public std::allocator<T>
{
public:
using std::allocator<T>::allocator;
template <class U, class... Args> void construct(U*, Args&&...) {}
};
template <typename VecType>
void init_vec(VecType &v)
{
// fill v with values [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
v.resize(10);
for (size_t i = 0; i < 10; ++i) v[i] = i; // Note this change!!!
// chop off the end of v, which now should be [1, 2, 3, 4, 5], but the other 5 values
// should remain in memory
v.resize(5);
}
template <typename VecType>
void print_vec(const char *label, VecType &v)
{
cout << label << ": ";
for (size_t i = 0; i < v.size(); ++i)
{
cout << v[i] << ' ';
}
cout << endl;
}
int
main()
{
std::vector<int, no_init_alloc<int>> std_vec;
init_vec(std_vec);
std_vec.resize(10);
print_vec("std", std_vec);
}
哪个应该输出:
std: 0 1 2 3 4 5 6 7 8 9
在no_init_alloc简单地拒绝做任何初始化,这是罚款int,有一个未确定的值离开它。我不得不更改您init_vec使用赋值来初始化而不是使用构造。因此,如果您不小心,可能会很危险/令人困惑。但是,它的确避免了不必要的初始化。
- 3 回答
- 0 关注
- 395 浏览
添加回答
举报