我正在寻找一种方法将一些数据填充到DLL边界的字符串中.因为我们使用不同的编译器,所有的dll接口都是简单的char*.
是否有正确的方法将指针传递给dll函数,以便它能够直接填充字符串缓冲区?
string stringToFillIn(100, '\0');
FunctionInDLL( stringToFillIn.c_str(), stringToFillIn.size() ); // definitely WRONG!
FunctionInDLL( const_cast<char*>(stringToFillIn.data()), stringToFillIn.size() ); // WRONG?
FunctionInDLL( &stringToFillIn[0], stringToFillIn.size() ); // WRONG?
stringToFillIn.resize( strlen( stringToFillIn.c_str() ) );
Run Code Online (Sandbox Code Playgroud)
看起来最有希望的是&stringToFillIn [0]但是这是一个正确的方法,假设你认为string :: data()==&string [0]?这似乎不一致.
或者最好是吞下额外的分配并避免问题:
vector<char> vectorToFillIn(100);
FunctionInDLL( &vectorToFillIn[0], vectorToFillIn.size() );
string dllGaveUs( &vectorToFillIn[0] );
Run Code Online (Sandbox Code Playgroud) (是的,我知道有一个问题几乎相同的标题,但得到的答复是不能令人满意的,见下文)
编辑抱歉,原始问题没有使用编译器优化.现在已经修复了这个问题,但是为了避免琐碎的优化并且更接近我的实际用例,测试已经分成两个编译单元.
std::vector<>
具有线性复杂性的构造函数在性能关键应用程序方面是一个令人讨厌的事实.考虑这个简单的代码
// compilation unit 1:
void set_v0(type*x, size_t n)
{
for(size_t i=0; i<n; ++i)
x[i] = simple_function(i);
}
// compilation unit 2:
std::vector<type> x(n); // default initialisation is wasteful
set_v0(x.data(),n); // over-writes initial values
Run Code Online (Sandbox Code Playgroud)
当构建时浪费了大量时间x
.正如这个问题所探讨的那样,传统的方法似乎只是保留存储和使用push_back()
来填充数据:
// compilation unit 1:
void set_v1(std::vector<type>&x, size_t n)
{
x.reserve(n);
for(size_t i=0; i<n; ++i)
x.push_back(simple_function(i));
}
// compilation unit 2:
std::vector<type> x(); x.reserve(n); // no initialisation
set_v1(x,n); // using push_back()
Run Code Online (Sandbox Code Playgroud)
然而,正如我的评论所指出的那样,push_back()
本质上是缓慢的,这使得第二种方法实际上比第一种方法慢 …
我有一个C++ 03应用程序,其中std::vector<T>
类型作为临时缓冲区使用.因此,它们通常会使用std::vector<T>::resize()
以确保它们足够大以在使用前保存所需数据.这个函数的C++ 03原型实际上是:
void resize(size_type n, value_type val = value_type());
Run Code Online (Sandbox Code Playgroud)
因此,实际上在调用时resize()
,通过添加适当数量的副本来放大矢量val
.但是,通常我只需要知道它vector
足够大以容纳我需要的数据; 我不需要用任何值初始化它.复制构造新值只是浪费时间.
C++ 11拯救了(我想):在它的规范中,它分为resize()
两个重载:
void resize(size_type n); // value initialization
void resize(size_type n, const value_type &val); // initialization via copy
Run Code Online (Sandbox Code Playgroud)
这非常适合C++的理念:只需支付你想要的东西.正如我所指出的那样,我的应用程序不能使用C++ 11,所以当我遇到Boost.Container库时,我很高兴,它表明在其文档中支持这个功能.具体来说,boost::container::vector<T>
实际上有三个重载resize()
:
void resize(size_type n); // value initialization
void resize(size_type n, default_init_t); // default initialization
void resize(size_type n, const value_type &val); // initialization via copy
Run Code Online (Sandbox Code Playgroud)
为了验证我理解了所有内容,我进行了快速测试以验证C++ 11的行为std::vector<T>
和boost::container::vector<T> …
我不明白为什么vector
在重新分配时应该使迭代器失效.
难道只是通过在迭代器中存储偏移量而不是指针来阻止这种情况吗?
为什么vector
没有这样设计?
class A {
public:
A();
private:
char a[5];
int* ptr;
};
A::A() : a(0), ptr(0) { }
Run Code Online (Sandbox Code Playgroud)
这是正确的吗?
如果没有整体阅读,请不要将其标记为重复.这不是"std :: reserve做什么"的问题.
使用内置类型写入vector :: reserve'd地址是错误的吗?
vector<int> vec;
vec.reserve(10);
vec[5] = 24; // Is this an error?
Run Code Online (Sandbox Code Playgroud)
我知道对象没有被初始化,但由于这些只是整数而空间是由保留分配的,而这是在连续存储中完成的,这是一个错误吗?
c++ ×6
vector ×3
c++11 ×2
boost ×1
constructor ×1
containers ×1
invalidation ×1
iterator ×1
string ×1