标签: c++03

如何使用weak_ptr中断shared_ptr循环引用

我已经读过weak_pointers可以用来打破循环引用.

请考虑以下循环引用示例

struct A
{
boost::shared_ptr<A> shrd_ptr;
};


boost::shared_ptr<A> ptr_A(boost::make_shared<A>());
boost::shared_ptr<A> ptr_b(boost::make_shared<A>());
ptr_A->shrd_ptr = ptr_b;
ptr_b->shrd_ptr = ptr_A;
Run Code Online (Sandbox Code Playgroud)

现在上面是一个循环引用的例子,我想知道如何通过使用来打破上面的循环引用weak_ptr

更新:根据收到的建议,我想出了以下内容:

struct A
{
  boost::weak_ptr<A> wk_ptr;
};

    boost::shared_ptr<A> ptr_A (boost::make_shared<A>());
    boost::shared_ptr<A> ptr_B (boost::make_shared<A>());
    ptr_A->wk_ptr = ptr_B;
    ptr_B->wk_ptr = ptr_A;
Run Code Online (Sandbox Code Playgroud)

这是正确的方法吗?

c++ smart-pointers c++03

14
推荐指数
1
解决办法
8592
查看次数

C++中的条件表达式是否总是bool类型?

在C面向条件运营商求值10类型的int(即使它确实有专用_Bool型).参考C11 N1570草案:

C11§6.5.8/ 6 关系运算符

如果指定的关系为真,则每个运算符<(小于),>(大于),<=(小于或等于)和>=(大于或等于)将产生1,如果为假,则为0.107)结果有类型int.

C11§6.5.9/ 3 平等运营商

==(等于)和!=(不等于)运算符类似于除了它们的优先级低的关系运算符.108)如果指定的关系为真,则每个运算符产生1,如果为假,则产生0.结果有类型int.对于任何一对操作数,其中一个关系是正确的.

C11 6.5.13/3 逻辑AND运算符

&&运营商将产生1,如果两个操作数的比较不等于0; 否则,它产生0.结果有类型int.

C11 6.5.14/3 逻辑OR运算符

||操作人员应得到1如果任一操作数的比较不等于0; 否则,它产生0.结果有类型int.

正如我检查的那样,C++似乎在这个问题上有所不同,如下面的示例所示(请参阅http://ideone.com/u3NxfW):

#include <iostream>
#include <typeinfo>

int main() {
    double x = 10.0;

    std::cout << typeid(x <= 10.0).name() << std::endl;

    return …
Run Code Online (Sandbox Code Playgroud)

c c++ language-lawyer c++11 c++03

14
推荐指数
2
解决办法
1005
查看次数

理解C++ 03运算符重载的标准语法

重载运算符的标准C++ 03语法如下:

operator-function-id:
运算 运算
运算 < template-argument-list?>

第一个是我们通常使用的普通运算符重载语法,例如

Myclass operator + (Myclass s) {...}
Run Code Online (Sandbox Code Playgroud)

但第二种选择意味着什么呢?特别是,在什么情况下我们使用template-argument-list?在快速浏览一下C++ 11之后,我发现第二种形式已经从标准中删除了.它的初衷是什么?

编辑:使用VC++ 2010测试后,下面是使用上述语法的一种方法,虽然它对我没有多大意义:

class K {
public:
    int a;
    template <int B>
    int operator + (int b) {
        return a+b+B;
    }
};


int _tmain(int argc, _TCHAR* argv[])
{
    K k;
    k.a=1;
    int s;
    s=k.operator+<115>(2);
    printf("%d\n",s);
    return 0;

}

output:118
Run Code Online (Sandbox Code Playgroud)

c++ language-lawyer c++03

14
推荐指数
1
解决办法
220
查看次数

线程安全的静态变量没有静音?

我记得读过在方法中声明的静态变量不是线程安全的.(请参阅托德加德纳提到的梅耶的单身人士怎么样)

Dog* MyClass::BadMethod()
{
  static Dog dog("Lassie");
  return &dog;
}
Run Code Online (Sandbox Code Playgroud)

我的库为最终用户生成C++代码,以便作为其应用程序的一部分进行编译.它生成的代码需要以线程安全的跨平台方式初始化静态变量.我想使用boost::call_once互斥变量初始化,但最后用户会暴露于Boost依赖项.

有没有办法让我这样做而不强迫最终用户有额外的依赖?

c++ boost initialization thread-safety c++03

13
推荐指数
1
解决办法
2万
查看次数

C++ 03中最接近浮点值的整数

对于某些整数类型,即使浮点值远远超出整数的可表示范围,如何找到最接近某个浮点类型值的值.

或者更确切地说:

我们F是一个浮点型(可能是float,doublelong double).让I是一个整数类型.

假设两个FI有有效的专业化std::numeric_limits<>.

给定可表示的值F,并且仅使用C++ 03,如何找到最接近的可表示值I

我追求的是一个纯粹,高效且线程安全的解决方案,除了C++ 03所保证的以外,它不会对平台做任何假设.

如果不存在这样的解决方案,是否可以使用C99/C++ 11的新功能找到一个?

lround()由于报告域错误的非平凡方式,使用C99似乎是有问题的.这些域错误是否可以以便携式和线程安全的方式捕获?

注意:我知道Boost可能通过其boost::numerics::converter<>模板提供解决方案,但由于其高复杂性和冗长性,我无法从中提取必需品,因此我无法检查他们的解决方案是否成功超出C++ 03的假设.

下面的天真方法失败了,因为I(f)当C++ 03的整数部分f不是可表示的值时,结果是未定义的I.

template<class I, class F> I closest_int(F f)
{
  return I(f);
}
Run Code Online (Sandbox Code Playgroud)

然后考虑以下方法:

template<class I, class F> I closest_int(F f)
{
  if (f < std::numeric_limits<I>::min()) return std::numeric_limits<I>::min();
  if (std::numeric_limits<I>::max() < f) return std::numeric_limits<I>::max();
  return I(f);
} …
Run Code Online (Sandbox Code Playgroud)

c++ floating-point type-conversion integral c++03

13
推荐指数
1
解决办法
806
查看次数

在C++ 11之前的"常量表达式"

constexpr关键字是在C++ 11中引入的,因为(我认为)是"常量表达式"的相应概念.但是,这个概念隐含在C++ 98/c ++ 03中,因为数组声明需要一个常量表达式:

// valid:
int a[sizeof(int)];
int b[3+7];
int c[13/4];
const int n = 3;
int d[n];
// invalid:
int m = 4;
int e[m];
Run Code Online (Sandbox Code Playgroud)

还有其他"常量表达式",即可以在编译时评估(和/或必须)的表达式; 一个例子是模板参数.

对于预C++ 11,在C++ 98/03标准或其他地方是否存在以下情况?

  • 需要常量表达式的语法结构的完整列表(例如数组声明和模板实例化)
  • 管理这种常量表达式的规则(可能这只是从上面列表中的项到它们在标准中的定义的映射)

c++ compile-time-constant constant-expression c++03 c++98

13
推荐指数
1
解决办法
1409
查看次数

如何打开文件进行读写,如果不存在则创建文件而不截断?

什么是适当的I/O标志集std::fstream,我希望能够读取写入文件,而不截断文件(如果存在),但如果不存在则创建它?

我试过了

std::ios::binary | std::ios::in | std::ios::out
std::ios::binary | std::ios::in | std::ios::out | std::ios::ate
Run Code Online (Sandbox Code Playgroud)

但如果文件尚不存在,则这些文件都不会创建.

我不想要std::ios::app,因为我还需要能够随意搜索文件,包括getput游标.

我认为,一种解决方法是实例化std::ofstream第一个,然后立即关闭它并打开我真正想要的流,但如果可以通过单个流对象避免它,那似乎很麻烦.

c++ fstream iostream c++03

13
推荐指数
1
解决办法
1522
查看次数

是否保证POD结构或标准布局类型的成员根据其对齐要求进行对齐?

给定POD结构(在C++ 03中)或标准布局类型(在C++ 11中),所有成员都具有基本对齐要求,是否保证每个成员根据其对齐要求进行对齐?

换句话说,对于m_k{ m0... mn}标准布局类型的所有成员S,

  struct S {
    T0 m0;
    T1 m1;
    ...
    TN mn;
  };
Run Code Online (Sandbox Code Playgroud)

是否保证评估以下表达式true

  (offsetof(S,m_k) % alignof(decltype(S::m_k))) == 0
Run Code Online (Sandbox Code Playgroud)

请给出C++ 03和C++ 11的答案,并引用标准的相关部分.支持C标准的证据也会有所帮助.


我对C++ 03标准(ISO/IEC 14882:2003(E))的阅读是关于POD结构中成员的对齐,除了第一个成员之外,它是静默的.相关段落是:

在规范的语言中,对象是"存储区域":

1.8 C + +对象模型[intro.object]

1.8/1 C++程序中的构造创建,销毁,引用,访问和操作对象.对象是存储区域....

根据对齐要求分配对象:

3.9类型[basic.types]

3.9/5对象类型具有对齐要求(3.9.1,3.9.2).完整对象类型的对齐是表示字节数的实现定义的整数值; 在满足其对象类型的对齐要求的地址处分配对象.

基本类型具有对齐要求:

3.9.1基本类型[basic.fundamental]

3.9.1/3对于每个有符号整数类型,存在相应的(但不同的)无符号整数类型:"unsigned char","unsigned short int","unsigned int"和"unsigned long int",每个它占用相同的存储量,并且具有与相应的有符号整数类型相同的对齐要求(3.9) ; ...

由于"实现对齐要求",可能会发生填充:

9.2班级成员[class.mem]

9.2/12声明没有插入访问说明符的(非联合)类的非静态数据成员,以便后面的成员在类对象中具有更高的地址.由访问说明符分隔的非静态数据成员的分配顺序未指定(11.1).实现对齐要求可能导致两个相邻成员不会立即分配 ; 因此,可能需要空间来管理虚拟功能(10.3)和虚拟基类(10.1).

9.2/12中的"已分配"一词与3.9/5中的"已分配"含义相同吗?规范中"分配"的大多数用法是指动态存储分配,而不是结构内部布局.使用可能在9.2/12中似乎意味着结构成员可能不严格要求3.9/5和3.9.1/3的对齐要求.

POD结构的第一个成员将根据结构的对齐要求进行对齐:

9.2/17指向POD结构对象的指针,使用reinterpret_cast进行适当转换,指向其初始成员(或者如果该成员是位字段,则指向它所在的单位),反之亦然.[ 注意:因此,在POD-struct对象中可能存在未命名的填充,但不是在其开头,以实现适当的对齐.]

[重点在上述所有引文中加入.]

c++ memory-alignment language-lawyer c++11 c++03

13
推荐指数
2
解决办法
784
查看次数

为什么GCC 6.3在没有明确的C++ 11支持的情况下编译这个Braced-Init-List代码?

我有一个关于卷括号括号列表的不同含义的问题.

我知道C++ 03不支持C++ 11 initializer_list.然而,即使没有-std=c++11编译器标志,gcc 6.3 也会interpolate使用以下代码正确初始化:

map<string, string> interpolate = { { "F", "a && b && c" }, { "H", "p ^ 2 + w" }, { "K", "H > 10 || e < 5" }, { "J", "F && !K" } };
Run Code Online (Sandbox Code Playgroud)

我被问到为什么这会起作用,我意识到我没有答案.这是一个Brace-Init-List,但我们从初始化标准容器的方式通常是通过initializer_list.那么非C++ 11代码如何完成初始化呢?

c++ gcc initializer-list c++03 list-initialization

13
推荐指数
1
解决办法
1450
查看次数

一元减的宏扩展

考虑以下代码:

#define A -100

//later..
void Foo()
{
  int bar = -A;
  //etc..
}
Run Code Online (Sandbox Code Playgroud)

现在,这可以在我测试的一些主要编译器(MSVC,GCC,Clang)上很好地进行编译,并且bar == 100按预期进行,这是因为所有这些编译器的预处理器在标记之间插入了一个空格,因此您最终得到:

int bar = - -100;
Run Code Online (Sandbox Code Playgroud)

因为我希望代码尽可能地可移植,所以我去检查此行为是否由标准定义,但是我在此上找不到任何东西。这种行为是由标准保证的还是仅仅是编译器功能,是否还bar = --100;允许幼稚的方法(显然不会进行编译)?

c++ c-preprocessor c++03

13
推荐指数
2
解决办法
193
查看次数