最近我从cppreference中读到了一个例子.../vector/emplace_back:
struct President
{
std::string name;
std::string country;
int year;
President(std::string p_name, std::string p_country, int p_year)
: name(std::move(p_name)), country(std::move(p_country)), year(p_year)
{
std::cout << "I am being constructed.\n";
}
Run Code Online (Sandbox Code Playgroud)
我的问题:这std::move真的需要吗?我的观点是,这p_name不是在构造函数体中使用,所以,也许,语言中有一些规则默认使用移动语义?
将std :: move初始化列表添加到每个重要成员(例如std::string,std::vector)会非常烦人.想象一下用C++ 03编写的数百个KLOC项目 - 我们是否应该添加到处std::move?
这个问题:move-constructor-and-initialization-list答案说:
作为一个黄金法则,无论何时你通过右值引用来获取内容,你需要在std :: move中使用它,并且每当你通过通用引用(即用&&推导出模板化类型)时,你需要在std ::里面使用它向前
但我不确定:通过价值而不是普遍的参考?
[UPDATE]
使我的问题更清楚.构造函数参数可以被视为XValue - 我的意思是到期值?
在这个例子AFAIK我们不使用std::move:
std::string getName()
{
std::string local = "Hello SO!";
return local; // std::move(local) is not needed nor …Run Code Online (Sandbox Code Playgroud) c++ language-lawyer initialization-list move-semantics c++11
在C++中有没有办法声明一个函数没有副作用?考虑:
LOG("message").SetCategory(GetCategory());
Run Code Online (Sandbox Code Playgroud)
现在假设发布版本中的LOG宏创建了一个NullLogEntry对象,该对象将SetCategory()定义为空函数.所以基本上整个表达式都可以(并且应该)被优化掉 - 从理论上说,GetCategory()调用可能会有一些副作用,所以我想编译器不允许抛弃它.
另一个示例可能是忽略其某些(或全部)参数的函数模板特化,但由于可能的副作用,编译器不允许在调用站点保存此类参数的评估.
我对吗?或者编译器能否最终优化此类调用?如果没有,有没有办法提示编译器这个函数没有副作用,所以如果忽略返回值那么可以跳过整个调用?
看完这个讨论后,我意识到我几乎完全误解了这件事:)
由于C++抽象机器的描述不够严格(例如,与JVM规范进行比较),如果无法得到准确的答案,我宁愿希望得到关于合理"好"的规则的非正式澄清(非恶意) )实施应遵循.
标准中关于实现自由的第1.9部分的关键概念被称为as-if规则:
只要可以从程序的可观察行为中确定,结果就好像符合要求一样,实施可以自由地忽略本标准的任何要求.
根据标准(I引用n3092),术语"可观察行为"表示以下内容:
- 严格根据抽象机的规则来评估对易失性对象的访问.
- 在程序终止时,写入文件的所有数据应与根据抽象语义产生的程序执行的可能结果之一相同.
- 交互设备的输入和输出动态应以在程序等待输入之前提示输出实际传送的方式进行.构成交互设备的是实现定义的.
因此,粗略地说,应保留易失性访问操作和io操作的顺序和操作数; 实现可以在保存这些不变量的程序中进行任意更改(与抽象c ++机器的某些允许行为相比)
期望非恶意实现对操作进行足够广泛的处理是否合理(例如,来自用户代码的任何系统调用都被视为此类操作)?(例如,如果RAII包装器不包含挥发物,则编译器不会丢弃RAII互斥锁定/解锁)
"行为观察"应该从用户定义的c ++程序级别深入到库/系统调用中有多深?现在的问题是,当然,只有该库的调用不打算有从用户角度来看IO /挥发性接入(例如,作为新/删除操作),而且可能(通常如此)访问挥发,或在图书馆/系统IO 实现.应该从用户的角度来看,编译器将这类电话(并考虑副作用,如没有可观察到的),或从"库"的观点(以及考虑的副作用观察到的)?
如果我需要通过编译器,以防止一些代码消除,这是一个好的做法,是不会问上面的所有问题,并简单地增加(可能是假的)挥发性存取操作(换行需要挥发的方法的行动,并呼吁他们对挥发性情况我在任何情况下似乎可疑?
或者我完全错了,除了标准明确提到的情况(作为副本消除)之外,编译器不允许删除任何c ++代码