小编Pot*_*ter的帖子

std :: initializer_list返回值的生命周期

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中的示例(如果它按照公布的方式工作)应该解决数组具有复制到对象的生命周期的歧义.然后返回值的数组也应该存在于调用函数中,并且应该可以通过将它绑定到命名引用来保留它.

LWS上 …

c++ lifetime initializer-list c++11 list-initialization

25
推荐指数
2
解决办法
4610
查看次数

XCode调试器很糟糕; 备择方案?

因为我是一个使用THINK C的小孩,我一直在Mac上编程.我从来没有像使用XCode那样使用调试器.

  • 它没有反应,并且在观察更多变量时进一步陷入困境并变得不稳定.
  • 当它崩溃时,我丢失了我的源的撤消历史记录,因为它与编辑器集成在一起.
  • 但是,它不会受益于集成,因为源查看器无法用于步进:尝试通过单击左边距选择一条线会使一个按钮从无处出现,导致程序继续到该行,在编辑器窗口中,这首先与调试无关.可怕的用户界面和糟糕的实施.
  • 一种蹒跚的漂亮数据"摘要"语法,它无法将对象发送到"表达式"窗口.
  • 表达式窗口始终不知道任何上下文.
  • 我无法选择要调试的特定线程,并且不会跳转到调用abort()的线程.

Mac OS 9内核调试器比这更好.是时候放弃了.

GDB在OS X上运行的独立前端是什么?我找到了http://ddd.darwinports.com/,但很难找到它或其他替代品的赞美或轶事.

支持STL容器对我来说是一个很大的优势.我对Objective-C或Apple-any不太关心.

c++ macos xcode

23
推荐指数
1
解决办法
6549
查看次数

Lambda捕获constexpr对象

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++ lambda constexpr c++11

22
推荐指数
1
解决办法
1893
查看次数

从工厂函数就地初始化不可复制的成员(或其他对象)

对于任何此语法,类必须具有有效的副本或移动构造函数才是合法的:

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语句解析如下:

  1. 6.6.3/2:"带有braced-init-list的return语句初始化了从指定的初始化列表中通过copy-list-initialization(8.5.4)从函数返回的对象或引用."
  2. 8.5.4/1:"复制初始化上下文中的列表初始化称为复制列表初始化." 3:"如果T是类类型,则考虑构造函数.枚举适用的构造函数,并通过重载解析(13.3,13.3.1.7)选择最佳构造函数."

不要被名称copy-list-initialization误导.8.5:

13:初始化的形式(使用括号或=)通常是无关紧要的,但是当初始化器或正在初始化的实体具有类类型时,它很重要; 见下文.如果正在初始化的实体没有类类型,则带括号的初始值设定项中的表达式列表应为单个表达式.

14:在表单 T x = a; 中以及在参数传递,函数返回,抛出异常(15.1),处理异常(15.3)和聚合成员初始化(8.5.1)时发生的初始化称为复制初始化.

当初始化器是braced-init-list时,复制初始化及其替代的直接初始化始终遵循列表初始化.添加时没有语义效果=,这是列表初始化非正式地称为统一初始化的一个原因.

存在差异:与复制初始化不同,直接初始化可以调用显式构造函数.复制初始化初始化临时并复制它以在转换时初始化对象.

的规范 …

c++ initialization copy-elision c++11

21
推荐指数
1
解决办法
2072
查看次数

每个线程都有自己的堆栈吗?

当我从进程创建多个线程时,每个线程是否都有自己的堆栈,或者它们是否共享其父进程的堆栈.线程进行系统调用时会发生什么?线程是否也像进程一样维护自己的内核堆栈?

c c++ stack multithreading pthreads

21
推荐指数
1
解决办法
8442
查看次数

钻石继承(C++)

我知道钻石继承被认为是不好的做法.但是,我有2个案例,我认为钻石继承可以很好地适应.我想问一下,您是否会建议我在这些情况下使用钻石继承,或者是否有其他设计可能更好.

案例1:我想在我的系统中创建代表不同类型"动作"的类.这些操作按以下几个参数进行分类:

  • 动作可以是"读取"或"写入".
  • 动作可以延迟或没有延迟(它不仅仅是1个参数.它会显着改变行为).
  • 动作的"流类型"可以是FlowA或FlowB.

我打算有以下设计:

// 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)

c++ oop inheritance multiple-inheritance diamond-problem

19
推荐指数
3
解决办法
1万
查看次数

如何防止模板类被多次派生?

我有以下模板类:

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.

有没有办法防止这样的模板类被多次派生?理想情况下,在这种情况下发出编译错误,或者至少是链接器错误.

c++ inheritance templates

19
推荐指数
2
解决办法
1012
查看次数

派生类中的成员new/delete重载是否有用?

我刚刚回答了一个关于缺少与新位置相对应的展示位置删除的问题.原因似乎operator delete是根据对象的动态类型调用的方式(对应于用于查找的类型operator new).

安置new对我有用.在自定义分配方面,可能存在一个可重用的类,其中不同的实例管理不同的池.单身人士是一种反模式,所有这一切.

我可以理解在new thing;不跟踪分配器的情况下完成工作的便利性,但是为类型层次结构的不同分支做事似乎相当复杂.

是否存在一个真实场景,派生类使用与其基础不同的分配器,并依赖虚拟析构函数来查找正确的成员operator delete

为了避免这种主观,我会接受最合理的答案.让我们不要嘲笑代码气味或"最好"的做事方式.

c++ inheritance operator-overloading new-operator

18
推荐指数
2
解决办法
1103
查看次数

SFINAE和decltype(自动)

如果函数模板返回decltype(auto)(或使用其他类型说明符auto)但返回语句格式不正确,SFINAE会导致吗?return声明是否被认为是函数签名的直接上下文?

N3690草案中的任何内容似乎都不需要这样.默认情况下,我猜SFINAE不适用.

这看起来很不幸,因为你可以编写一个函数来转发给另一个函数,但是当你写一个longhand时,你不能让它的存在以委托为条件.此外,decltype(auto)由于this不能在函数签名中使用,因此无法检查是否存在对等非静态成员函数.然而,这表明存在一个基本问题,因为decltype(auto)它提供了一种在成员签名中将类类型视为完整的路径,而不是.

是否已撰写提案,或者是否已在任何地方对问题进行了正式分析?

在成员签名中将类类型视为完整的能力可能具有其他含义......但这只是另一个问题的素材.

c++ decltype auto c++14

18
推荐指数
1
解决办法
1067
查看次数

字符串文字可以在常量表达式中下标吗?

这是有效的,因为一个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)

c++ string-literals constexpr c++11

17
推荐指数
1
解决办法
2267
查看次数