如何获取std :: vector缓冲区的地址最优雅?

sha*_*oth 12 c++ stl vector

我想使用std :: vector来动态分配内存.场景是:

int neededLength = computeLength(); // some logic here

// this will allocate the buffer     
std::vector<TCHAR> buffer( neededLength );

// call a function that accepts TCHAR* and the number of elements
callFunction( &(buffer[0]), buffer.size() );
Run Code Online (Sandbox Code Playgroud)

上面的代码有效,但这&(buffer[0])看起来很难看.是否有更优雅的方式来实现相同的目标?

小智 24

没人知道这真是奇怪!在C++ 11中你可以使用:

buffer.data()
Run Code Online (Sandbox Code Playgroud)

它可以得到我测试它的向量的地址:

vector<char>buffer;
buffer.push_back('w');
buffer.push_back('h');
buffer.push_back('a');
buffer.push_back('t');
buffer.push_back('\0');
char buf2[10];
memcpy(buf2,buffer.data(),10);
Run Code Online (Sandbox Code Playgroud)

规格在这里.

  • 请注意,该问题是在 C++11 创建前 3 年发布的 (3认同)
  • 缓冲区大小可能小于 10 字节,但您复制了 10 字节,可能会崩溃 (2认同)

小智 20

好吧,你可以删除一组parens:

&buffer[0]
Run Code Online (Sandbox Code Playgroud)

但这是常见的,惯用的方式.如果真的冒犯了你,我想你可以使用一个模板 - 比如:

template <typename T> 
T * StartOf( std::vector <T> & v ) {
    return &v[0];
}
Run Code Online (Sandbox Code Playgroud)

  • 在函数中执行此操作后,您也可以使用它来检查容器是否为空. (5认同)
  • 似乎是对我"断言"的完美用法. (4认同)
  • 对你来说可能有所不同,但在过去十年左右的时间里,我将这样的代码放到每个人的工具箱中.而且由于我几乎无法控制其他人在做什么,所以无论我自己的需求是什么,我都会至少对其进行调试检查. (2认同)
  • 好吧,C ++的哲学一直是“不要为不使用的东西付钱”,这是我非常认同的哲学。当然,您无法控制人们如何使用您的API,但这是他们的问题,而不是您的问题。 (2认同)

sbi*_*sbi 19

实际上,&buffer[0](注意没有parantheses)的主要问题并不是它不是真的很漂亮.(无论如何,这是主观的.buffer.begin(), buffer.end()当我第一次学会使用STL时,我记得发现并不漂亮.)

主要问题是它在buffer空的时候调用未定义的行为- 大多数代码从不检查它.这就是我将这些放入我的工具箱的原因:

template <class T, class TAl>
inline T* begin_ptr(std::vector<T,TAl>& v)
{return  v.empty() ? NULL : &v[0];}

template <class T, class TAl>
inline const T* begin_ptr(const std::vector<T,TAl>& v)
{return  v.empty() ? NULL : &v[0];}

template <class T, class TAl>
inline T* end_ptr(std::vector<T,TAl>& v)
{return v.empty() ? NULL : (begin_ptr(v) + v.size());} 

template <class T, class TAl>
inline const T* end_ptr(const std::vector<T,TAl>& v)
{return v.empty() ? NULL : (begin_ptr(v) + v.size());}
Run Code Online (Sandbox Code Playgroud)

使用这些,您可以将代码编写为

callFunction( begin_ptr(buffer), buffer.size() );
Run Code Online (Sandbox Code Playgroud)

是否begin_ptr(buffer)&buffer[0]您留下的更漂亮.但是,鉴于NULL应该检查每个指针函数参数,它肯定更安全.

  • @mmutz:我不是强烈赞成或反对`NULL` /`0`.这主要是一个风格问题(虽然`NULL`更适合grep).实际上,在原始代码中我使用了`0`.当我将代码复制到帖子中时,我只更改了这个,因为我认为这里看到的"NULL"比"0"更多.:○> (2认同)

Kon*_*lph 12

但这&(buffer[0])看起来很难看

这是正常的方式.但是,您可以省略括号:

&buffer[0]
Run Code Online (Sandbox Code Playgroud)


P S*_*ved 7

没有.

  • 如果它传达了错误的答案,那么简洁就没有任何意义.Neil和我都发布了更简单的解决方案(降低了17%的字符数). (2认同)