我有一些使用类型惩罚的代码,以避免必须调用成员"对象"的构造函数和析构函数,除非/直到实际需要使用该对象.
它工作正常,但在g ++ 4.4.3下,我得到了这个可怕的编译器警告:
jaf@jeremy-desktop:~$ g++ -O3 -Wall puns.cpp
puns.cpp: In instantiation of ‘Lightweight<Heavyweight>’:
puns.cpp:68: instantiated from here
puns.cpp:12: warning: ignoring attributes applied to ‘Heavyweight’ after definition
puns.cpp: In destructor ‘Lightweight<T>::~Lightweight() [with T = Heavyweight]’:
puns.cpp:68: instantiated from here
puns.cpp:20: warning: dereferencing type-punned pointer will break strict-aliasing rules
puns.cpp: In member function ‘void Lightweight<T>::MethodThatGetsCalledRarely() [with T = Heavyweight]’:
puns.cpp:70: instantiated from here
puns.cpp:36: warning: dereferencing type-punned pointer will break strict-aliasing rules
Run Code Online (Sandbox Code Playgroud)
我的代码尝试使用gcc的__attribute((__ may_alias__))让gcc知道潜在的别名,但是gcc似乎并不理解我想告诉它的内容.我做错了什么,或者gcc 4.4.3只是在__may_alias__属性上遇到了一些问题?
重现编译器警告的玩具代码如下:
#include <stdio.h>
#include <memory> // …Run Code Online (Sandbox Code Playgroud) (5.2.10/6)C++ 03指向函数的指针可以显式转换为指向不同类型函数的指针.通过指向函数类型(8.3.5)的函数调用函数的效果是未定义的,该函数类型与函数定义中使用的类型不同.除了将"指向T1的指针"的rvalue转换为"指向T2的指针"类型(其中T1和T2是函数类型)并返回其原始类型产生原始指针值之外,这种指针转换的结果未指定.[注意:有关指针转换的更多详细信息,另请参见4.10.]
以下是我正在尝试做的事情,虽然很明显转换fp1为的结果fp2将产生一个原始指针,但在同一点上标准中的措辞是"The result of such a pointer conversion is unspecified"什么意思呢?
int f() { return 42; }
int main()
{
void(*fp1)() = reinterpret_cast<void(*)()>(f);
int(*fp2)() = reinterpret_cast<int(*)()>(fp1);
// Safe to call the function ?
fp2();
}
Run Code Online (Sandbox Code Playgroud) 以下是否调用未定义的行为?
int x;
int i = x;
Run Code Online (Sandbox Code Playgroud)
参考C++ 03
(4.1/1)如果左值引用的对象不是类型T的对象,并且不是从T派生的类型的对象,或者如果对象未初始化,则需要此转换的程序具有未定义的行为.
编辑: 但是,从(3.3.1/1)开始,对象可能会使用自己的不确定值进行初始化,为什么会这样?即
int x = x; //not an undefined behaviour
Run Code Online (Sandbox Code Playgroud) 我正在创建一些旨在提供对回调功能的访问的接口.也就是说,继承自接口A允许类使用类型1的回调; 接口B允许类型2.继承A和B允许两种类型的回调.最终目的是A类和B类通过继承它们来处理所有脏工作.
这是一个小例子,应该说明我遇到的一些麻烦:
class A
{
public:
static void AFoo( void* inst )
{
((A*)inst)->ABar( );
}
virtual void ABar( void ) = 0;
};
class B
{
public:
static void BFoo( void* inst )
{
((B*)inst)->BBar( );
}
virtual void BBar( void ) = 0;
};
class C : public A, public B
{
public:
void ABar( void ){ cout << "A"; };
void BBar( void ){ cout << "B"; };
};
Run Code Online (Sandbox Code Playgroud)
通过拨打电话
C* c_inst …Run Code Online (Sandbox Code Playgroud) 我正在阅读boost::shared_ptr源代码并发现它使用此函数来增加shared_ptr的使用计数(引用计数):
inline void atomic_increment( int * pw )
{
//atomic_exchange_and_add( pw, 1 );
__asm__
(
"lock\n\t"
"incl %0":
"=m"( *pw ): // output (%0)
"m"( *pw ): // input (%1)
"cc" // clobbers
);
}
Run Code Online (Sandbox Code Playgroud)
为什么不简单地使用operator++这样做呢?这会带来更好的表现吗?
在下面的代码std::cout中不打印值,但printf确实如此.为什么是这样?
#include <iostream>
#include <cstdio>
struct bits
{
union
{
unsigned char b;
struct
{
unsigned char b0:1, b1:1, b2:1, b3:1, b4:1, b5:1, b6:1, b7:1;
};
};
};
const union
{
bits b[3];
char c[3];
} CU = { .c = { -1, 0, 1 }};
int main()
{
std::cout << "----- chars:\n";
std::cout << "\tstd::cout (c): " << CU.c[0]
<< ", " << CU.c[1]
<< ", " << CU.c[2]
<< "\n";
printf("\tprintf (c): %d, %d, …Run Code Online (Sandbox Code Playgroud) 我正在尝试一个简单的C++继承示例.但我无法理解.当我尝试B从类继承的类的受保护成员时,A它表示A::baz受保护.
#include <iostream>
class A {
public:
int foo;
int bar;
protected:
int baz;
int buzz;
private:
int privfoo;
int privbar;
};
class B : protected A {}; // protected members go to class B, right?
int main() {
B b;
b.baz; // here is the error [A::baz is protected]
}
Run Code Online (Sandbox Code Playgroud)
我似乎无法找到我做错的事.我试图改变class B : protected A到: public A,但它仍然无法正常工作.
在看到 Herb Sutters关于“原子武器”的精彩演讲后,我对放松原子的例子感到有些困惑。
我认为C++ 内存模型(SC-DRF = Sequentially Consistent for Data Race Free)中的原子在加载/读取时执行“获取”。
我知道对于负载 [和存储] 是默认值std::memory_order_seq_cst,因此两者是相同的:
myatomic.load(); // (1)
myatomic.load(std::memory_order_seq_cst); // (2)
Run Code Online (Sandbox Code Playgroud)
到目前为止一切都很好,没有涉及放松的原子(在听完演讲后,我永远不会使用放松的原子。永远。承诺。但当有人问我时,我可能不得不解释......)。
但是为什么我使用时它是“宽松”的语义
myatomic.load(std::memory_order_acquire); // (3)
Run Code Online (Sandbox Code Playgroud)
既然负载是获取而不是释放,为什么这与(1)和不同(2)?究竟是在这里放松?
我唯一能想到的就是我误解了load意味着acquire。如果这是真的,并且默认值seq_cst意味着两者,那不就意味着一个完整的围栏 - 没有任何东西可以传递该指令,也不能传递?我一定误解了那部分。
[并且对称地用于存储和释放]。
使用enabled_shared_from_this时似乎有一些边缘情况.例如:
可以在不需要enable_shared_from_this的情况下实现shared_from_this吗?如果是这样,它可以快速制作吗?
c++ multiple-inheritance shared-ptr weak-ptr enable-shared-from-this
假设您有以下类层次结构:
class A
{
public:
virtual void foo() {}
}
class B
{
public:
virtual void foo() {}
}
class C: public A, public B
{
public:
virtual void foo() override { } // This overrides both
}
class D: public A, public B
{
public:
// Is there syntax so that there is a separate override for each?
// Maybe something like:
// virtual void A::foo() override {}
// virtual void B::foo() override {}
}
Run Code Online (Sandbox Code Playgroud)
有没有办法在D类上有两个foo函数,这样如果D作为对A的引用传递,则调用D中的一个函数,如果D作为对B的引用传递,则D中的不同函数是叫什么名字?
用例是如果你从两个外部库继承,它们碰巧有重叠的函数说明符?
c++ ×10
inheritance ×2
shared-ptr ×2
atomicity ×1
boost ×1
casting ×1
cout ×1
gcc ×1
memory-model ×1
overriding ×1
pointers ×1
printf ×1
protected ×1
static-cast ×1
stdatomic ×1
type-punning ×1
weak-ptr ×1