GCC的实现破坏了std::initializer_list返回full-expression结束时从函数返回的数组.它是否正确?
此程序中的两个测试用例都显示在使用值之前执行的析构函数:
#include <initializer_list>
#include <iostream>
struct noisydt {
~noisydt() { std::cout << "destroyed\n"; }
};
void receive( std::initializer_list< noisydt > il ) {
std::cout << "received\n";
}
std::initializer_list< noisydt > send() {
return { {}, {}, {} };
}
int main() {
receive( send() );
std::initializer_list< noisydt > && il = send();
receive( il );
}
Run Code Online (Sandbox Code Playgroud)
我认为该计划应该有效.但潜在的标准有点令人费解.
return语句初始化一个返回值对象,就像它被声明一样
std::initializer_list< noisydt > ret = { {},{},{} };
Run Code Online (Sandbox Code Playgroud)
这initializer_list将从给定的初始化器系列初始化一个临时及其底层数组存储,然后initializer_list从第一个初始化器初始化另一个.阵列的寿命是多少?"数组的生命周期与initializer_list对象的生命周期相同." 但其中有两个; 哪一个是模棱两可的.8.5.4/6中的示例(如果它按照公布的方式工作)应该解决数组具有复制到对象的生命周期的歧义.然后返回值的数组也应该存在于调用函数中,并且应该可以通过将它绑定到命名引用来保留它.
因为我是一个使用THINK C的小孩,我一直在Mac上编程.我从来没有像使用XCode那样使用调试器.
Mac OS 9的内核调试器比这更好.是时候放弃了.
GDB在OS X上运行的独立前端是什么?我找到了http://ddd.darwinports.com/,但很难找到它或其他替代品的赞美或轶事.
支持STL容器对我来说是一个很大的优势.我对Objective-C或Apple-any不太关心.
GCC 4.7.2编译:
constexpr int i = 5;
[]{ std::integral_constant< int, i >(); }; // nonstandard: i not captured
Run Code Online (Sandbox Code Playgroud)
但不是这个:
constexpr int i = 5;
[&i]{ std::integral_constant< int, i >(); }; // GCC says i not constexpr
Run Code Online (Sandbox Code Playgroud)
根据C++11§5.1.2/ 15,后一个例子对我来说是正确的:
如果实体是隐式或显式捕获但未通过复制捕获,则通过引用捕获实体.未指定是否在闭包类型中为通过引用捕获的实体声明了其他未命名的非静态数据成员.
似乎ilambda中捕获的对象引用了封闭范围中的变量constexpr,而不仅仅是const引用.
该标准明确指出,使用按值捕获转换为对lambda对象的相应成员的使用.我认为5.1.2提示我的解释是正确的.
是否有任何明确说明通过引用捕获是否引用封闭范围中的对象或引用?
对于任何此语法,类必须具有有效的副本或移动构造函数才是合法的:
C x = factory();
C y( factory() );
C z{ factory() };
Run Code Online (Sandbox Code Playgroud)
在C++ 03中,依赖复制省略来阻止编译器触及复制构造函数是相当普遍的.无论定义是否存在,每个类都有一个有效的复制构造函数签名.
在C++ 11中,应该定义一个不可复制的类型C( C const & ) = delete;,无论使用什么,对函数的任何引用都是无效的(对于不可移动的相同).(C++11§8.4.3/ 2).例如,GCC会在尝试按值返回此类对象时抱怨.复制省立不再有帮助.
幸运的是,我们还有新的语法来表达意图而不是依赖于漏洞.该factory函数可以返回一个braced-init-list来临时构造结果:
C factory() {
return { arg1, 2, "arg3" }; // calls C::C( whatever ), no copy
}
Run Code Online (Sandbox Code Playgroud)
编辑:如果有任何疑问,此return语句解析如下:
不要被名称copy-list-initialization误导.8.5:
13:初始化的形式(使用括号或
=)通常是无关紧要的,但是当初始化器或正在初始化的实体具有类类型时,它很重要; 见下文.如果正在初始化的实体没有类类型,则带括号的初始值设定项中的表达式列表应为单个表达式.14:在表单
T x = a;中以及在参数传递,函数返回,抛出异常(15.1),处理异常(15.3)和聚合成员初始化(8.5.1)时发生的初始化称为复制初始化.
当初始化器是braced-init-list时,复制初始化及其替代的直接初始化始终遵循列表初始化.添加时没有语义效果=,这是列表初始化非正式地称为统一初始化的一个原因.
存在差异:与复制初始化不同,直接初始化可以调用显式构造函数.复制初始化初始化临时并复制它以在转换时初始化对象.
的规范 …
当我从进程创建多个线程时,每个线程是否都有自己的堆栈,或者它们是否共享其父进程的堆栈.线程进行系统调用时会发生什么?线程是否也像进程一样维护自己的内核堆栈?
我知道钻石继承被认为是不好的做法.但是,我有2个案例,我认为钻石继承可以很好地适应.我想问一下,您是否会建议我在这些情况下使用钻石继承,或者是否有其他设计可能更好.
案例1:我想在我的系统中创建代表不同类型"动作"的类.这些操作按以下几个参数进行分类:
我打算有以下设计:
// abstract classes
class Action
{
// methods relevant for all actions
};
class ActionRead : public virtual Action
{
// methods related to reading
};
class ActionWrite : public virtual Action
{
// methods related to writing
};
class ActionWithDelay : public virtual Action
{
// methods related to delay definition and handling
};
class ActionNoDelay : public virtual Action {/*...*/};
class ActionFlowA : public virtual Action {/*...*/};
class ActionFlowB : public …Run Code Online (Sandbox Code Playgroud) 我有以下模板类:
template<class I>
class T : public I
{
// ...
};
Run Code Online (Sandbox Code Playgroud)
对于给定的模板参数,此模板类需要一次(且仅一次)派生I.
class A : public T<U> {}; // ok
class B : public T<V> {}; // ok
class C : public T<U> {}; // compile error
Run Code Online (Sandbox Code Playgroud)
模板类T可以适合于实现这样的行为(而类A,B,U,V不能); 但是,T决不能有关于派生类的任何知识A,B,C.
有没有办法防止这样的模板类被多次派生?理想情况下,在这种情况下发出编译错误,或者至少是链接器错误.
我刚刚回答了一个关于缺少与新位置相对应的展示位置删除的问题.原因似乎operator delete是根据对象的动态类型调用的方式(对应于用于查找的类型operator new).
安置new对我有用.在自定义分配方面,可能存在一个可重用的类,其中不同的实例管理不同的池.单身人士是一种反模式,所有这一切.
我可以理解在new thing;不跟踪分配器的情况下完成工作的便利性,但是为类型层次结构的不同分支做事似乎相当复杂.
是否存在一个真实场景,派生类使用与其基础不同的分配器,并依赖虚拟析构函数来查找正确的成员operator delete?
为了避免这种主观,我会接受最合理的答案.让我们不要嘲笑代码气味或"最好"的做事方式.
如果函数模板返回decltype(auto)(或使用其他类型说明符auto)但返回语句格式不正确,SFINAE会导致吗?return声明是否被认为是函数签名的直接上下文?
N3690草案中的任何内容似乎都不需要这样.默认情况下,我猜SFINAE不适用.
这看起来很不幸,因为你可以编写一个函数来转发给另一个函数,但是当你写一个longhand时,你不能让它的存在以委托为条件.此外,decltype(auto)由于this不能在函数签名中使用,因此无法检查是否存在对等非静态成员函数.然而,这表明存在一个基本问题,因为decltype(auto)它提供了一种在成员签名中将类类型视为完整的路径,而不是.
是否已撰写提案,或者是否已在任何地方对问题进行了正式分析?
在成员签名中将类类型视为完整的能力可能具有其他含义......但这只是另一个问题的素材.
这是有效的,因为一个constexpr表达式被允许取的值"文字类型的glvalue其指的是与constexpr定义的非挥发性物体,或者是指这样的对象的一个子对象"(§5.19/ 2 ):
constexpr char str[] = "hello, world";
constexpr char e = str[1];
Run Code Online (Sandbox Code Playgroud)
但是,似乎字符串文字不符合此描述:
constexpr char e = "hello, world"[1]; // error: literal is not constexpr
Run Code Online (Sandbox Code Playgroud)
2.14.5/8描述了字符串文字的类型:
普通字符串文字和UTF-8字符串文字也称为窄字符串文字.窄字符串文字具有类型"n const char数组",其中n是下面定义的字符串的大小,并且具有静态存储持续时间.
看起来这种类型的对象可以被索引,只要它是临时的而不是静态存储持续时间(5.19/2,就在上面的代码片段之后):
[
constexpr允许lvalue-to-rvalue转换] ...一个文字类型的glvalue,引用一个非易失性临时对象,其生命周期尚未结束,用一个常量表达式初始化
这是特别奇怪的,因为取一个临时对象的左值通常是"作弊".我想这个规则适用于引用类型的函数参数,例如in
constexpr char get_1( char const (&str)[ 6 ] )
{ return str[ 1 ]; }
constexpr char i = get_1( { 'y', 'i', 'k', 'e', 's', '\0' } ); // OK
constexpr char e = get_1( "hello" ); // error: string …Run Code Online (Sandbox Code Playgroud)