考虑一个需要复制的类。拷贝中的绝大多数数据元素必须严格反射(reflect)原始数据,但是只有少数元素的状态不需要保留,需要重新初始化。
从复制构造函数调用默认赋值运算符是不是不好的形式?
默认的赋值运算符可以很好地处理普通旧数据(int、double、char、short)以及用户定义的每个赋值运算符的类。指针需要单独处理。
一个缺点是,由于没有执行额外的重新初始化,这种方法会使赋值运算符失效。也不可能禁用赋值运算符,因此打开了用户使用不完整的默认赋值运算符 A obj1,obj2; 创建损坏类的选项;对象 2=对象 1;/* 结果可能是一个错误初始化的 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);
printf("Y: %d %d %d %d\n",Y.a,Y.b,Y.c,Y.d);
输出:
X: 123 456 789 987
Y: 123 456 0 987
替代拷贝构造函数:
A(const A & orig):a(orig.a),b(orig.b),c(0),d(orig.d){} /* <-- is this "better"? */
最佳答案
正如 brone 指出的那样,您最好在复制构造方面实现分配。我更喜欢他的替代成语:
T& T::operator=(T t) {
swap(*this, t);
return *this;
}
它有点短,can take advantage of some esoteric language features以提高性能。就像任何优秀的 C++ 代码一样,它也有一些需要注意的细微之处。
首先,t参数是故意传值的,这样会调用拷贝构造函数(most of the time),在不影响原值的情况下,可以随心所欲地修改。使用 const T& 会编译失败,而 T& 会通过修改assigned-from值来触发一些令人惊讶的行为。
此技术还要求 swap 以不使用类型的赋值运算符的方式专门用于该类型(如 std::swap 所做的那样),或者它将导致无限递归。小心任何杂散的 using std::swap 或 using namespace std,因为它们会将 std::swap 拉入范围并在以下情况下导致问题您没有专门针对 T 进行 swap。重载分辨率和ADL如果您已定义它,将确保使用正确版本的交换。
有几种方法可以为类型定义 swap。第一种方法使用 swap 成员函数来完成实际工作,并有一个委托(delegate)给它的 swap 特化,如下所示:
class T {
public:
// ....
void swap(T&) { ... }
};
void swap(T& a, T& b) { a.swap(b); }
这在标准库中很常见;例如,std::vector 已经以这种方式实现了交换。如果你有一个 swap 成员函数,你可以直接从赋值运算符调用它,避免函数查找出现任何问题。
另一种方法是将 swap 声明为友元函数并让它完成所有工作:
class T {
// ....
friend void swap(T& a, T& b);
};
void swap(T& a, T& b) { ... }
我更喜欢第二个,因为 swap() 通常不是类接口(interface)的组成部分;它似乎更适合作为免费功能。然而,这是一个品味问题。
对类型进行优化的 swap 是实现 C++0x 中右值引用的一些好处的常用方法,因此一般来说,如果类可以利用它和你真的需要性能。
关于c++ - 从复制构造函数调用默认赋值运算符是不好的形式吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1533725/
我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server
我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re
请帮助我理解范围运算符...和..之间的区别,作为Ruby中使用的“触发器”。这是PragmaticProgrammersguidetoRuby中的一个示例:a=(11..20).collect{|i|(i%4==0)..(i%3==0)?i:nil}返回:[nil,12,nil,nil,nil,16,17,18,nil,20]还有:a=(11..20).collect{|i|(i%4==0)...(i%3==0)?i:nil}返回:[nil,12,13,14,15,16,17,18,nil,20] 最佳答案 触发器(又名f/f)是
我正在尝试用ruby中的gsub函数替换字符串中的某些单词,但有时效果很好,在某些情况下会出现此错误?这种格式有什么问题吗NoMethodError(undefinedmethod`gsub!'fornil:NilClass):模型.rbclassTest"replacethisID1",WAY=>"replacethisID2andID3",DELTA=>"replacethisID4"}end另一个模型.rbclassCheck 最佳答案 啊,我找到了!gsub!是一个非常奇怪的方法。首先,它替换了字符串,所以它实际上修改了
我有一些代码在几个不同的位置之一运行:作为具有调试输出的命令行工具,作为不接受任何输出的更大程序的一部分,以及在Rails环境中。有时我需要根据代码的位置对代码进行细微的更改,我意识到以下样式似乎可行:print"Testingnestedfunctionsdefined\n"CLI=trueifCLIdeftest_printprint"CommandLineVersion\n"endelsedeftest_printprint"ReleaseVersion\n"endendtest_print()这导致:TestingnestedfunctionsdefinedCommandLin
如何在Ruby中按名称传递函数?(我使用Ruby才几个小时,所以我还在想办法。)nums=[1,2,3,4]#Thisworks,butismoreverbosethanI'dlikenums.eachdo|i|putsiend#InJS,Icouldjustdosomethinglike:#nums.forEach(console.log)#InF#,itwouldbesomethinglike:#List.iternums(printf"%A")#InRuby,IwishIcoulddosomethinglike:nums.eachputs在Ruby中能不能做到类似的简洁?我可以只
如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:
说在前面这部分我本来是合为一篇来写的,因为目的是一样的,都是通过独立按键来控制LED闪灭本质上是起到开关的作用,即调用函数和中断函数。但是写一篇太累了,我还是决定分为两篇写,这篇是调用函数篇。在本篇中你主要看到这些东西!!!1.调用函数的方法(主要讲语法和格式)2.独立按键如何控制LED亮灭3.程序中的一些细节(软件消抖等)1.调用函数的方法思路还是比较清晰地,就是通过按下按键来控制LED闪灭,即每按下一次,LED取反一次。重要的是,把按键与LED联系在一起。我打算用K1来作为开关,看了一下开发板原理图,K1连接的是单片机的P31口,当按下K1时,P31是与GND相连的,也就是说,当我按下去时
我需要一个通过输入字符串进行计算的方法,像这样function="(a/b)*100"a=25b=50function.something>>50有什么方法吗? 最佳答案 您可以使用instance_eval:function="(a/b)*100"a=25.0b=50instance_evalfunction#=>50.0请注意,使用eval本质上是不安全的,尤其是当您使用外部输入时,因为它可能包含注入(inject)的恶意代码。另请注意,a设置为25.0而不是25,因为如果它是整数a/b将导致0(整数)。
我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我