我想知道我的构造函数的最佳形式。下面是一些示例代码:
class Y { ... }
class X
{
public:
X(const Y& y) : m_y(y) {} // (a)
X(Y y) : m_y(y) {} // (b)
X(Y&& y) : m_y(std::forward<Y>(y)) {} // (c)
Y m_y;
}
Y f() { return ... }
int main()
{
Y y = f();
X x1(y); // (1)
X x2(f()); // (2)
}
最佳答案
我已经拼凑了一些例子。我在所有这些中都使用了 GCC 4.4.4。
简单案例,不带 -std=c++0x
首先,我将一个非常简单的示例放在一起,其中包含两个接受 std::string 的类。每个。
#include <string>
#include <iostream>
struct A /* construct by reference */
{
std::string s_;
A (std::string const &s) : s_ (s)
{
std::cout << "A::<constructor>" << std::endl;
}
A (A const &a) : s_ (a.s_)
{
std::cout << "A::<copy constructor>" << std::endl;
}
~A ()
{
std::cout << "A::<destructor>" << std::endl;
}
};
struct B /* construct by value */
{
std::string s_;
B (std::string s) : s_ (s)
{
std::cout << "B::<constructor>" << std::endl;
}
B (B const &b) : s_ (b.s_)
{
std::cout << "B::<copy constructor>" << std::endl;
}
~B ()
{
std::cout << "B::<destructor>" << std::endl;
}
};
static A f () { return A ("string"); }
static A f2 () { A a ("string"); a.s_ = "abc"; return a; }
static B g () { return B ("string"); }
static B g2 () { B b ("string"); b.s_ = "abc"; return b; }
int main ()
{
A a (f ());
A a2 (f2 ());
B b (g ());
B b2 (g2 ());
return 0;
}
stdout 上的输出如下:A::<constructor>
A::<constructor>
B::<constructor>
B::<constructor>
B::<destructor>
B::<destructor>
A::<destructor>
A::<destructor>
A或 B离开。a, a2, b, b2 的代码。就地,即使调用了一个看似按值返回的函数。从而 GCC 可以避免许多可能通过查看代码而“推断”出存在的临时变量。std::string 的频率在上面的例子中实际上是复制的。让我们替换 std::string用一些我们可以更好地观察和看到的东西。-std=c++0x#include <string>
#include <iostream>
struct S
{
std::string s_;
S (std::string const &s) : s_ (s)
{
std::cout << " S::<constructor>" << std::endl;
}
S (S const &s) : s_ (s.s_)
{
std::cout << " S::<copy constructor>" << std::endl;
}
~S ()
{
std::cout << " S::<destructor>" << std::endl;
}
};
struct A /* construct by reference */
{
S s_;
A (S const &s) : s_ (s) /* expecting one copy here */
{
std::cout << "A::<constructor>" << std::endl;
}
A (A const &a) : s_ (a.s_)
{
std::cout << "A::<copy constructor>" << std::endl;
}
~A ()
{
std::cout << "A::<destructor>" << std::endl;
}
};
struct B /* construct by value */
{
S s_;
B (S s) : s_ (s) /* expecting two copies here */
{
std::cout << "B::<constructor>" << std::endl;
}
B (B const &b) : s_ (b.s_)
{
std::cout << "B::<copy constructor>" << std::endl;
}
~B ()
{
std::cout << "B::<destructor>" << std::endl;
}
};
/* expecting a total of one copy of S here */
static A f () { S s ("string"); return A (s); }
/* expecting a total of one copy of S here */
static A f2 () { S s ("string"); s.s_ = "abc"; A a (s); a.s_.s_ = "a"; return a; }
/* expecting a total of two copies of S here */
static B g () { S s ("string"); return B (s); }
/* expecting a total of two copies of S here */
static B g2 () { S s ("string"); s.s_ = "abc"; B b (s); b.s_.s_ = "b"; return b; }
int main ()
{
A a (f ());
std::cout << "" << std::endl;
A a2 (f2 ());
std::cout << "" << std::endl;
B b (g ());
std::cout << "" << std::endl;
B b2 (g2 ());
std::cout << "" << std::endl;
return 0;
}
S::<constructor>
S::<copy constructor>
A::<constructor>
S::<destructor>
S::<constructor>
S::<copy constructor>
A::<constructor>
S::<destructor>
S::<constructor>
S::<copy constructor>
S::<copy constructor>
B::<constructor>
S::<destructor>
S::<destructor>
S::<constructor>
S::<copy constructor>
S::<copy constructor>
B::<constructor>
S::<destructor>
S::<destructor>
B::<destructor>
S::<destructor>
B::<destructor>
S::<destructor>
A::<destructor>
S::<destructor>
A::<destructor>
S::<destructor>
S创建者 B的构造函数。使用 S 的默认复制构造函数没有改变这一点。换 f, g成为static A f () { return A (S ("string")); } // still one copy
static B g () { return B (S ("string")); } // reduced to one copy!
B 构造参数。的构造函数就位但犹豫要不要构造 B的成员就位。A或 B被创建。这意味着 a, a2, b, b2仍在原地 build 。凉爽的。-std=c++0xS S (S &&s) : s_ ()
{
std::swap (s_, s.s_);
std::cout << " S::<move constructor>" << std::endl;
}
B的构造函数 B (S &&s) : s_ (std::move (s)) /* how many copies?? */
{
std::cout << "B::<constructor>" << std::endl;
}
S::<constructor>
S::<copy constructor>
A::<constructor>
S::<destructor>
S::<constructor>
S::<copy constructor>
A::<constructor>
S::<destructor>
S::<constructor>
S::<move constructor>
B::<constructor>
S::<destructor>
S::<constructor>
S::<move constructor>
B::<constructor>
S::<destructor>
B::<destructor>
S::<destructor>
B::<destructor>
S::<destructor>
A::<destructor>
S::<destructor>
A::<destructor>
S::<destructor>
g, g2static B g () { S s ("string"); return B (s); }
static B g2 () { S s ("string"); s.s_ = "abc"; B b (s); /* s is zombie now */ b.s_.s_ = "b"; return b; }
B的构造函数带有一个接受常量左值引用的构造函数。 B (S const &s) : s_ (s)
{
std::cout << "B::<constructor2>" << std::endl;
}
g, g2导致“constructor2”被调用,因为符号 s在任何一种情况下,都更适合 const 引用而不是右值引用。g 中做一个 Action 以两种方式之一:static B g () { return B (S ("string")); }
static B g () { S s ("string"); return B (std::move (s)); }
f到static void f (A &result) { A tmp; /* ... */ result = tmp; } /* or */
static void f (A &result) { /* ... */ result = A (S ("string")); }
A的任务提供了它。复制到result不能跳过,也不能tmp代替 result build , 自 result没有被 build 。因此,它比以前慢,不需要复制。 C++0x 编译器和移动赋值运算符会减少开销,但它仍然比按值返回慢。S的构造函数对自身成员履行基本保证,对全局项履行强保证,整个按值返回的过程实际上提供了强有力的保证。T& T::operator=(T const& x) // x is a reference to the source
{
T tmp(x); // copy construction of tmp does the hard work
swap(*this, tmp); // trade our resources for tmp's
return *this; // our (old) resources get destroyed with tmp
}
T& T::operator=(T x) // x is a copy of the source; hard work already done
{
swap(*this, x); // trade our resources for x's
return *this; // our (old) resources get destroyed with x
}
swap ,无论如何都要考虑按值传递(在 C++0x 之前)swap可能比复制东西更有效。考虑 S的构造函数是 S (std::string s) : s_ (/* is this cheap for your std::string? */)
{
s_.swap (s); /* then this may be faster than copying */
std::cout << " S::<constructor>" << std::endl;
}
关于c++ - 构造函数的最佳形式?传值还是传引用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4321305/
很好奇,就使用rubyonrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提
我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
我的瘦服务器配置了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中的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
我想让一个yaml对象引用另一个,如下所示:intro:"Hello,dearuser."registration:$introThanksforregistering!new_message:$introYouhaveanewmessage!上面的语法只是它如何工作的一个例子(这也是它在thiscpanmodule中的工作方式。)我正在使用标准的rubyyaml解析器。这可能吗? 最佳答案 一些yaml对象确实引用了其他对象:irb>require'yaml'#=>trueirb>str="hello"#=>"hello"ir
我有一个名为posts的模型,它有很多附件。附件模型使用回形针。我制作了一个用于创建附件的独立模型,效果很好,这是此处说明的View(https://github.com/thoughtbot/paperclip):@attachment,:html=>{:multipart=>true}do|form|%>posts中的嵌套表单如下所示:prohibitedthispostfrombeingsaved:@attachment,:html=>{:multipart=>true}do|at_form|%>附件记录已创建,但它是空的。文件未上传。同时,帖子已成功创建...有什么想法吗?
如何在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.你能做的最好的事情是: