我发现MSVC和GCC编译器每个类实例至少分配一个字节,即使该类是没有成员变量的谓词(或只有静态成员变量).以下代码说明了这一点.
#include <iostream>
class A
{
public:
bool operator()(int x) const
{
return x>0;
}
};
class B
{
public:
static int v;
static bool check(int x)
{
return x>0;
}
};
int B::v = 0;
void test()
{
A a;
B b;
std::cout << "sizeof(A)=" << sizeof(A) << "\n"
<< "sizeof(a)=" << sizeof(a) << "\n"
<< "sizeof(B)=" << sizeof(B) << "\n"
<< "sizeof(b)=" << sizeof(b) << "\n";
}
int main()
{
test();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出:
sizeof(A)=1
sizeof(a)=1
sizeof(B)=1 …Run Code Online (Sandbox Code Playgroud) 有时类会引用其他类.实现std::swap()这样的类不是直截了当的,因为它会导致原始实例而不是引用的交换.下面的代码说明了这种行为:
#include <iostream>
class A
{
int& r_;
public:
A(int& v) : r_(v) {}
void swap(A& a)
{
std::swap(r_, a.r_);
}
};
void test()
{
int x = 10;
int y = 20;
A a(x), b(y);
a.swap(b);
std::cout << "x=" << x << "\n"
<< "y=" << y << "\n";
}
int main()
{
test();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
联合的简单解决方法:
class A
{
union
{
int& r_;
size_t t_;
};
public:
A(int& v) : r_(v) {}
void swap(A& a) …Run Code Online (Sandbox Code Playgroud) 最近,我不得不用一组类似的容器替换单个容器。因此,我需要一个保留原始迭代器语义的组合迭代器。我遇到的问题是处理组合的 end() 位置。由于无法比较未分配的迭代器,我不得不将所有四个迭代器都包含为成员(即两个范围,外部和内部)。这导致 operator==() 在最常见的情况下需要三个比较。当然,这比普通嵌套循环中的比较(在最常见的情况下需要单个比较)要糟糕得多。除此之外,我注意到四个迭代器代码容易出错,因为如果容器内容在循环内发生变化,将 end() 迭代器保留在组合迭代器中可能会导致跳过 for() 循环的退出条件。
template <class T>
class MyContainer
{
typedef std::vector<T> Inner;
typedef std::vector<Inner> Outer;
Outer v_;
public:
class iterator
{
friend class MyContainer;
Outer::iterator it1_, it1end_;
Inner::iterator it2_, it2end_;
iterator(Outer::iterator it1, Outer::iterator it1end) :
it1_(it1), it1end_(it1end)
{
if(it1_!=it1end_) {
it2_ = it1_->begin();
it2end_ = it1_->end();
}
}
public:
bool operator==(iterator it) const {
return it1_==it.it1_ &&
(it1_==it1end_ || it2_==it.it2_);
}
};
iterator begin() { return iterator(v_.begin(), v_.end()); }
iterator end() { return iterator(v_.end(), …Run Code Online (Sandbox Code Playgroud) 我需要使用qsort稳定排序数组.为了确保结果稳定,我在比较函数中添加了一个额外条件:
int compare(const void *p1, const void *p2)
{
if(*(const Data*)p1 < *(const Data*)p2)
return -1;
if(*(const Data*)p2 < *(const Data*)p1)
return 1;
else
return p1<p2 ? -1 : 1;
}
Run Code Online (Sandbox Code Playgroud)
如果qsort从不调用compare(p,p),这将有效.否则我需要使用更复杂的条件.问题是,qsort是否曾经使用重复指针调用compare(),还是总是比较不同的指针?
更新:
我用Ideone C++编译器检查了这个:https://ideone.com/l026kM
对于注释中的小例子{8,8,1,1},提供的qsort()实现不会改变指针的顺序,也不会为同一元素调用compare.这似乎是合理的,因为每次反向交换都会影响性能,因为它需要稍后进行交换.我将使用随机生成的数组和不同的编译器来测试它.
更新:
在Ideone上测试100000个随机数组,重复键的最小份额为80%.结果是100%稳定的排序数组.这是链接:https://ideone.com/KOYbgJ
VC++ Express 2008编译器无法稳定排序,因为指针的顺序已更改.这基本上说明了VC++实现与GCC实现的不同之处在于它不保持指针顺序.