启用swapSTL算法的正确方法是什么?
1)会员swap.是否std::swap使用SFINAE技巧来使用该成员swap.
2)自由站立swap在同一名称空间中.
3)部分专业化std::swap.
4)以上所有.
谢谢.
编辑:看起来我没有清楚地说出我的问题.基本上,我有一个模板类,我需要STL algos来使用我为该类编写的(高效)交换方法.
考虑一个简单的程序:
int main() {
int* ptr = nullptr;
delete ptr;
}
Run Code Online (Sandbox Code Playgroud)
对于GCC(7.2),在结果程序中有call关于的指令operator delete.对于Clang和Intel编译器,没有这样的指令,空指针删除被完全优化(-O2在所有情况下).你可以在这里测试:https://godbolt.org/g/JmdoJi.
我想知道这样的优化能否以某种方式与GCC一起开启?(我更广泛的动机源于自定义swapvs std::swap可移动类型的问题,其中删除空指针可能代表第二种情况下的性能损失; 有关详细信息,请参阅/sf/answers/3198249771/.)
UPDATE
为了澄清我对这个问题的动机:如果我在移动赋值运算符和某个类的析构函数中使用delete ptr;无if (ptr)保护,那么该类的对象将产生3个GCC指令.这可能是相当大的性能损失,例如,在对这些对象的数组进行排序时.std::swapcall
此外,我可以if (ptr) delete ptr;在任何地方写作,但是想知道,这是否也不能成为性能损失,因为delete表达式也需要检查ptr.但是,在这里,我想,编译器只会生成一个检查.
此外,我真的很喜欢delete没有后卫的可能性,这对我来说是一个惊喜,它可以产生不同的(表现)结果.
UPDATE
我只是做了一个简单的基准测试,即排序对象,它们delete在移动赋值运算符和析构函数中调用.来源是:https://godbolt.org/g/7zGUvo
std::sort使用GCC 7.1测量的运行时间和-O2Xeon E2680v3上的标志:
链接代码中存在一个错误,它会比较指针,而不是指向值.更正结果如下:
if后卫:可能重复:
移动语义==自定义交换功能已过时?
这就是std::swapC++ 11中的样子:
template<typename T>
void swap(T& x, T& y)
{
T z = std::move(x);
x = std::move(y);
y = std::move(z);
}
Run Code Online (Sandbox Code Playgroud)
如果我的类定义了移动构造函数和移动赋值运算符,我还是必须专注std::swap于我自己的类型,或者它会std::swap尽可能高效吗?
可能重复:
如何为我的班级提供交换功能?
关于这一点存在一些问题,但是很多矛盾(A人给出了解决方案A',其中有很多人用B表示它是UB)或者"仅在编译器支持ADL时才有效".
所以,假设我有以下模板(容器)类:
template<typename T>
class C {
// ...
void swap(C<T>& y) throw(); // C x; x.swap(y);
}
Run Code Online (Sandbox Code Playgroud)
那么确保这个(示例)代码有效的正确方法是什么:
C<int> x, y;
std::swap(x, y);
Run Code Online (Sandbox Code Playgroud)
请给出你对C++ 03的答案,如果它仍然适用于C++ 0x,那就更好了!
考虑一个自定义类,X其中包含一些资源(为了简单起见,这里用整数成员变量表示),其中包含移动构造函数 (MC)、移动赋值运算符 (MAO) 和自定义交换函数:
class X {
int i_;
public:
X(int i) : i_(i) { }
X(X&& rhs) = default; // move constructor
X& operator=(X&& rhs) = default; // move assignment operator
// X& operator=(X rhs) { std::swap(i_, rhs.i_); return *this; } // unifying assign. op.
friend void swap(X& lhs, X& rhs) { std::swap(lhs.i_, rhs.i_); }
int i() const { return i_; }
};
Run Code Online (Sandbox Code Playgroud)
在以下基准代码中:
int main() {
int i1, i2;
std::cin >> i1 >> i2;
X x1(i1), …Run Code Online (Sandbox Code Playgroud) 编码
using namespace std;
class A
{
private:
vector<int> a;
public:
A(vector<int> x):a(x){}
string toString()
{
string s;
for (auto& element : a)
{
s += to_string(element) + " ";
}
return s;
}
};
int main()
{
A a1({1,2,3});
A a2({11,12,13});
cout << "a1 = " << a1.toString() << "\n";
cout << "a2 = " << a2.toString() << "\n";
swap(a1,a2);
cout << "a1 = " << a1.toString() << "\n";
cout << "a2 = " << a2.toString() << "\n";
return …Run Code Online (Sandbox Code Playgroud)