因此,在观看了关于右值引用的精彩演讲之后,我认为每个类都会受益于这样的"移动构造函数",template<class T> MyClass(T&& other) 编辑,当然还有"移动赋值运算符",template<class T> MyClass& operator=(T&& other)正如Philipp在他的回答中指出的,如果它已经动态分配成员,或通常存储指针.就像你应该有一个copy-ctor,赋值运算符和析构函数,如果之前提到的点适用.思考?
有时重新开始很好.在C++中,我可以使用以下简单的操作:
{
T x(31, Blue, false);
x.~T(); // enough with the old x
::new (&x) T(22, Brown, true); // in with the new!
// ...
}
Run Code Online (Sandbox Code Playgroud)
在范围的最后,析构函数将再次运行,一切似乎都很好.(我们也说T有点特别,不喜欢被分配,更不用说交换了.)但有些东西告诉我,摧毁一切并再试一次并不总是没有风险.这种方法有可能存在吗?
我今天读到一些有趣的内容,说用户提供的类型(作为模板参数提供)调用swap的"标准"方式是......
using std::swap;
swap(something, soemthingelse);
Run Code Online (Sandbox Code Playgroud)
这样做的原因是使用的参数依赖查找要么使用一个swap在用户的命名空间或函数swap的std命名空间.这为我提出了一个感兴趣的问题.当我超载std::swap了我的课之一,我实际上已被定义它的std命名空间... namespace std { void swap(/*...*/){/*...*/} }.这种做法错了吗?我应该定义自己的swaps std或我自己的命名空间(以及为什么)?
我希望在示例中,bellow编译器将无法编译代码,因为它不知道什么是"find()",它在算法头中的std命名空间中定义.
但是,此代码使用gcc 4.1.2在RHEL 5.3上编译.
我错过了什么?
#include <string>
#include <algorithm>
int main()
{
std::string s;
find(s.begin(), s.end(), 'a'); // should not compile
}
Run Code Online (Sandbox Code Playgroud) 向std命名空间添加类型是否可以接受.例如,我想要一个TCHAR友好的字符串,以下是可接受的吗?
#include <string>
namespace std
{
typedef basic_string<TCHAR> tstring;
}
Run Code Online (Sandbox Code Playgroud)
或者我应该使用自己的命名空间?
可能重复:
如何为我的班级提供交换功能?
每次我认为我理解它,我都会看到让我感到困惑的事情.
如果您想swap为自己的课程提供实施,您会怎么做?
可能性列表如下:
在std命名空间中定义一个(带两个参数),在下面调用#3
(有人说这是正确的;有些人说非法)
在类中定义一个静态方法,接受两个参数交换
(对我来说比#4更有意义,但我不明白为什么没有人这样做),它会swap根据需要调用任何基类
定义一个实例方法的类的内部,采取一个其他参数与交换,它调用任何基础类swapS作为必要
定义一个实例方法的类中,以2个其它参数来交换,也这里,任何基础类这就要求swapS作为必要
还有别的
我自己的理解是,我需要#5,#3,凡来电将被调用swap一样using std::swap; swap(a, b);,但似乎没有人认为联合是真正困惑我的事实.我真的根本不理解#4,因为实际上每个人似乎都在使用实例成员,而实际操作是静态的.我无法分辨我的理解是错误的还是我在查看时看到的一堆答案.
什么是正确的方法?
在什么是复制和交换习语这个例子显示:
friend void swap(dumb_array& first, dumb_array& second) // nothrow
{
// enable ADL (not necessary in our case, but good practice)
using std::swap;
// by swapping the members of two classes,
// the two classes are effectively swapped
swap(first.mSize, second.mSize);
swap(first.mArray, second.mArray);
}
Run Code Online (Sandbox Code Playgroud)
如何using std::swap启用ADL?ADL只需要一个不合格的名称.我看到的唯一好处using std::swap是,因为std::swap是一个函数模板,你可以在call(swap<int, int>(..))中使用模板参数列表.
如果不是这样的话,那是using std::swap为了什么?
考虑一类需要复制的副本.副本中的绝大多数数据元素必须严格反映原始数据元素,但是有少数元素的状态不被保留且需要重新初始化.
从复制构造函数调用默认赋值运算符是不好的形式?
默认赋值运算符对于Plain Old Data(int,double,char,short)以及每个赋值运算符的用户定义类都表现良好.指针需要单独处理.
一个缺点是该方法使得赋值运算符瘫痪,因为不执行额外的重新初始化.也无法禁用赋值运算符的使用,从而通过使用不完整的默认赋值运算符打开用户创建损坏类的选项A obj1,obj2; obj2=obj1; /* Could result is an incorrectly initialized obj2 */.
a(orig.a),b(orig.b)...除了a(0),b(0) ...必须写之外,放宽要求是很好的.需要写入所有初始化两次会产生两个错误位置,如果double x,y,z要将新变量(例如)添加到类中,初始化代码需要在至少2个位置而不是1个位置正确添加.
有没有更好的办法?
在C++ 0x中有更好的方法吗?
class A {
public:
A(): a(0),b(0),c(0),d(0)
A(const A & orig){
*this = orig; /* <----- is this "bad"? */
c = int();
}
public:
int a,b,c,d;
};
A X;
X.a = 123;
X.b = 456;
X.c = 789;
X.d = 987;
A Y(X);
printf("X: %d %d %d %d\n",X.a,X.b,X.c,X.d); …Run Code Online (Sandbox Code Playgroud) C++标准禁止在命名空间中声明类型或定义任何内容std,但它允许您为用户定义的类型专门化标准STL模板.
通常,当我想专注std::swap于我自己的自定义模板类型时,我只是这样做:
namespace std
{
template <class T>
void swap(MyType<T>& t1, MyType<T>& t2)
{
t1.swap(t2);
}
}
Run Code Online (Sandbox Code Playgroud)
......这很好.但我不完全确定我的惯常做法是否符合标准.我这样做了吗?
我正在研究这个关于实现用户定义类型函数的最佳实践的微妙问题的这个有趣的答案.(我的问题最初的动机是讨论将名称添加到命名空间的非法性.)swapstd
我不会在这里重新打印上面链接的答案中的代码片段.
相反,我想了解答案.
答案我上面的状态联系在一起,第一代码片段之下,在关于超载swap的namespace std(而不是专门在的命名空间):
如果您的编译器打印出不同的东西,那么它就不能正确地为模板实现"两阶段查找".
然后答案指出,专门swap研究namespace std(而不是重载它)会产生不同的结果(在专业化的情况下是期望的结果).
但是,答案继续进行另外一种情况:为用户定义的模板类专门交换 - 在这种情况下,再次无法实现所需的结果.
不幸的是,答案只是陈述事实; 它没有解释原因.
有人可以详细说明这个答案,并在该答案中提供的两个特定代码片段中描述查找过程:
过载swap在namespace std为用户定义的非模板类(如在联答复的第一代码段)
专注swap于namespace std用户定义的模板类(如链接答案的最终代码段)
在这两种情况下,std::swap都会调用泛型,而不是用户定义的泛型swap.为什么?
(这将阐明两阶段查找的本质,以及实现用户定义swap的最佳实践的原因;谢谢.)