我想添加一个函数,它将.size()值作为整数返回,而不是无符号整数。
编辑:由于评论,我解释得更详细:
我有代码:
int something = 3;
if(arr.size() > something)
哪会产生编译器警告,我不喜欢添加(int)到我拥有它的每个地方。 所以,我认为使用sizei()函数会很好:
int something = 3;
if(arr.sizei() > something)
哪个不会产生警告。
所以,我不想创建一个单独的函数,而是std :: vector本身的函数。
编辑:似乎唯一的方法就是创建另一个功能,例如:
template <typename T>
inline int sizei(const T &arr){
return (int)arr.size();
}
从积极的方面来看:这根本不会增加我的可执行文件大小。
答案 0 :(得分:6)
首先,你为什么要这样?我没有看到任何理由或优势:
无论如何,你可以这样做:
template<typename T>
int size(const std::vector<T> &v) { return (int) v.size(); }
//use
std::vector<int> ints;
//...
int count = size(ints);
我仍然没有看到这样做的任何意义。你可以简单地写一下:
int count = (int) ints.size();
但我仍然会说它并不比以下更好:
size_t count = ints.size(); //don't prefer anything over this. Always use size_t
int
大小。首选size_t
。关于你问题的编辑。为什么不使用size_t
作为:
size_t something = 3;
if(arr.size() > something)
没有警告。在我看来,如果您在整个程序中一致地选择数据类型,那么当您要将int
与size_t
进行比较时,您就不会遇到这种情况,该int
被定义为 unsigned 整数型。
或者,如果您有一些遗留代码要使用,并且使用int something = /*some legacy code API call or something */;
if(arr.size() > (size_t) something)
//or even better;
size_t something = (size_t) /*some legacy code API call or something */;
if(arr.size() > something)
作为大小,那么我认为在您需要时使用显式强制转换更好,而不是在框架本身隐藏了潜在的问题:
{{1}}
答案 1 :(得分:2)
通常,在C和C ++中,不应使用size_t
等无符号类型来限制域。这是因为(1)这些语言不提供范围检查,(2)它们确实提供了不合理的隐式促销。没有范围检查意味着(1)没有优势,不合理的隐含促销意味着(2)非常不利的缺点,所以这是非常愚蠢的事情:没有优势,非常不利的缺点。
但是,这些语言的标准库可以做到这一点。他们只为历史原因做这件事,在早期决定中不可逆转地抓住了,这在某个时候是有意义的。这具有非常愚蠢的后果,例如C99需要ptrdiff_t
的17(!)位,并且它具有上述非常不期望的后果,例如使用非常多的时间来搜寻由隐式促销(等)导致的错误。例如,在C ++中,你几乎可以保证std::string( "bah!" ).length() < -5
- 这很容易让你绊倒,无论如何都像设计一样愚蠢。
现在,您无法在std::vector
中注入新的成员函数,但您可以添加一个独立的函数。一个好名字是countOf
。模板使它可以应用于任何事物(原始数组,向量等)。
据我所知,函数的三元组startOf
,endOf
和countOf
首先由Dietmar Kuehl确定。 C ++ 0x将有std::begin
和std::end
,但AFAIK没有对应的std::size
。在此期间,您可以定义此支持,它允许您处理任何类型的容器和原始数组相同。
一个示例实现&amp; my blog提供了进一步的讨论。
编辑添加一些代码,因为它已在评论中提出。
检测合适的迭代器类型:
template< typename Type >
struct It
{
typedef typename Type::iterator T;
};
template< typename Type >
struct It< Type const >
{
typedef typename Type::const_iterator T;
};
template< typename ElemType, Size N >
struct It< ElemType[N] >
{
typedef ElemType* T;
};
countOf
,startOf
和endOf
函数,使用推导的迭代器类型:
template< typename T >
inline Size countOf( T const& c ) { return static_cast<Size>( c.size() ); }
template< typename T, Size N >
inline Size countOf( T (&)[N] ) { return N; }
template< typename T >
inline typename It<T>::T startOf( T& c ) { return c.begin(); }
template< typename T, Size N >
inline T* startOf( T (&a)[N] ) { return a; }
template< typename T >
inline typename It<T>::T endOf( T& c ) { return c.end(); }
template< typename T, Size N >
inline T* endOf( T (&a)[N] ) { return a + N; }
其中Size
是ptrdiff_t
的typedef。
注意:在64位Windows int
(甚至long
)中是32位。因此,对于非常大的数组,int
通常是不够的。 ptrdiff_t
保证能够表示任何两个指针之间的差异,当明确定义差异时。
干杯&amp;第h
答案 2 :(得分:1)
我倾向于使用显式强制转换为 int 而不是函数:static_cast<int> (v.size())
。更好的是在处理内存大小时始终使用size_t
。例如,支持for (size_t i=0; i < v.size(); ++i)
而不是for (int i=0; i < (int) v.size(); ++i)
。使用正确的类型进行工作。您不应该将std :: vector大小与签名类型进行比较。
请参阅以下参考资料,了解为什么您更喜欢size_t到int:
答案 3 :(得分:1)
您可以按照以下方式从向量派生:
template<typename T>
class my_vector : public vector<T>
{
// missing constructors!
int size() const
{
if (vector<T>::size() > INT_MAX)
throw std::range_error("too many elements in vector");
return (int) vector<T>::size();
}
};
缺点是你必须自己定义和转发构造函数。
答案 4 :(得分:0)
.size()的快速回答是:不。对于向量,可能性是其存储值和alloc方法(默认new
/ delete
,通常不会被覆盖)以及使用InputIterator
的方法。
大多数人会问为什么你想要一个不同的size_t
。如果它只是烦人的警告,你可以强制转换或使用无符号整数来对size()进行迭代/检查。 (如果它是很多代码,你将不得不寻找/替换)...如果它处理空条件,你可以将矢量包装在一个带有一些智能的类中。顺便说一句,因为我不知道你手头的问题,所以查找想法和已经实现的功能的好地方是std库的算法,例如sort
,for_each
,find
,等等。
对于std算法,请参阅:http://www.sgi.com/tech/stl/table_of_contents.html
答案 5 :(得分:0)
虽然@Nawaz在我看来提供了最恰当的答案,但如果你真的想在std :: vector&lt;&gt;中添加一个额外的成员这真的不可能。 @zvrba提供了唯一可以实现的方法,但正如评论中所述,std容器类型没有虚拟析构函数,因此不应该是子类。
但是,您可以使用容器适配器实现一种新类型的向量,如下所示:
template <class T>
class my_vector
{
public:
int size_i() const
{
return static_cast<int>(container_.size());
}
private:
std::vector<T> container_;
};
这里的缺点是你必须明确地公开你实际需要支持的容器的功能。如果您在整个代码中正常使用'std :: vector',这可能是一个重大变化。有关容器适配器的实现示例,请参阅“std :: queue”。