相关疑难解决方法(0)

标准布局c ++

我正在阅读关于C++ POD,Trivial和Standard Layout类的精彩文章 我对标准布局没有清楚了解的一个属性如下: -

 A standard layout has no base classes of the same type as the first 
    non-static data member
Run Code Online (Sandbox Code Playgroud)

因此,以下将不是标准布局,因为它具有与基类相同的第一个成员

struct NonStandardLayout3 : StandardLayout1 {
    StandardLayout1 x; // first member cannot be of the same type as base
};
Run Code Online (Sandbox Code Playgroud)

但是在性能方面和属性方面,上述结构有何不同

struct StandardLayout5 : StandardLayout1 {
    int x;
    StandardLayout1 y; // can have members of base type if they're not the first   
};
Run Code Online (Sandbox Code Playgroud)

这是对此之上的修正.

c++ pod standard-layout c++11

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

is_standard_layout如何有用?

据我所知,标准布局允许三件事:

  • 空基类优化
  • 向后兼容C与某些指针转换
  • 使用offsetof

现在,包含在库中的是is_standard_layout谓词元函数,但我在通用代码中看不到它的用处,因为我上面列出的那些C特性似乎极少需要检查通用代码.我唯一能想到的是在里面使用它static_assert,但这只是为了使代码更健壮而且不是必需的.

怎么is_standard_layout有用?有没有没有它的东西是不可能的,因此需要它在标准库中?

c++ standard-layout c++11

12
推荐指数
1
解决办法
1223
查看次数

在C中包装C++:派生到基本转换

我将一个简单的C++继承层次结构包装成"面向对象的"C.我试图弄清楚是否有任何问题将C++对象的指针视为指向不透明C结构的指针.特别是,在什么情况下派生到基础的转换会导致问题?

类本身相对复杂,但层次结构很浅并且仅使用单继承:

// A base class with lots of important shared functionality
class Base {
    public:
    virtual void someOperation();
    // More operations...

    private:
    // Data...
};

// One of several derived classes
class FirstDerived: public Base {
    public:
    virtual void someOperation();
    // More operations...

    private:
    // More data...
};

// More derived classes of Base..
Run Code Online (Sandbox Code Playgroud)

我计划通过以下相当标准的面向对象的C向C客户端展示它:

// An opaque pointers to the types
typedef struct base_t base_t;
typedef struct first_derived_t first_derived_t;

void base_some_operation(base_t* object) {
     Base* base = (Base*) object; …
Run Code Online (Sandbox Code Playgroud)

c c++ oop standard-layout

5
推荐指数
1
解决办法
667
查看次数

仅通过指针强制转换即可互换类类型,而不必分配任何新对象?

更新:我非常感谢“不要那样,要这样”的建议。它们很有用,尤其是在有启发性的情况下提供时。仍然……不管优缺点,我一直好奇地找到一个坚定不移的“是的,可以在C ++ 11中合法地完成”“没有,不可能那样做”


我想“别名”一个对象指针作为另一种类型,其唯一目的是添加一些辅助方法。别名不能将数据成员添加到基础类中(实际上,我可以阻止它发生的次数越多越好!)所有别名都同样适用于此类型的任何对象……如果类型系统可以提示哪个别名,则只会有帮助别名可能是最合适的。

应该没有有关在基础对象中编码的任何特定别名的信息。因此,我觉得您应该能够“欺骗”类型系统,并使其成为注解...在编译时进行检查,但最终与运行时转换无关。遵循以下原则:

Node<AccessorFoo>* fooPtr = Node<AccessorFoo>::createViaFactory();
Node<AccessorBar>* barPtr = reinterpret_cast< Node<AccessorBar>* >(fooPtr);
Run Code Online (Sandbox Code Playgroud)

在幕后,factory方法实际上是在创建一个NodeBase类,然后使用类似的方法reinterpret_cast将其返回为a Node<AccessorFoo>*

避免这种情况的简单方法是使这些轻量级类包装节点并按值传递。因此,您不需要强制转换,只需将带有节点句柄的Accessor类包装在其构造函数中即可:

AccessorFoo foo (NodeBase::createViaFactory());
AccessorBar bar (foo.getNode());
Run Code Online (Sandbox Code Playgroud)

但是,如果我不必为此付出任何代价,那我就不想。例如,这将涉及为每种包装的指针(AccessorFooShared,AccessorFooUnique,AccessorFooWeak等)创建一种特殊的访问器类型,最好将这些类型化的指针别名为一个基于单个指针的对象标识,并提供一个很好的正交性。

回到最初的问题:

Node<AccessorFoo>* fooPtr = Node<AccessorFoo>::createViaFactory();
Node<AccessorBar>* barPtr = reinterpret_cast< Node<AccessorBar>* >(fooPtr);
Run Code Online (Sandbox Code Playgroud)

似乎有某种方法可以做到这一点可能很丑陋,但不能“违反规则”。根据ISO14882:2011(e)5.2.10-7

可以将对象指针显式转换为其他类型的对象指针。70将“指向T1的指针”的prvalue v转换为“指向Cv T2的指针”时,结果为static_cast(static_cast(v))如果T1和T2均为标准布局类型(3.9),并且T2的对齐要求不严格于T1的对齐要求,或者任一类型均无效。将类型为“指向T1的指针”的prvalue转换为“指向T2的指针”的类型(其中T1和T2是对象类型,并且T2的对齐要求不严格于T1的对齐要求)并返回其原始类型指针值。未指定任何其他此类指针转换的结果。

深入研究“标准布局类”的定义,我们发现:

  • 没有非标准布局类(或此类数组)或引用类型的非静态数据成员,并且
  • 没有虚拟函数(10.3)和虚拟基类(10.1),并且
  • 对所有非静态数据成员具有相同的访问控制(第11条),并且
  • 没有非标准布局的基类,并且
  • 在派生最多的类中没有非静态数据成员,并且最多有一个具有非静态数据成员的基类,或者没有具有非静态数据成员的基类,并且
  • 没有与第一个非静态数据成员相同类型的基类。

听起来像使用类似的东西会有点费劲,而访问器或节点中没有虚拟方法。但是C ++ 11显然必须std::is_standard_layout保持检查状态。

这样可以安全吗?似乎可以在gcc-4.7中使用,但是我想确定自己没有调用未定义的行为。

c++ language-lawyer reinterpret-cast type-punning c++11

4
推荐指数
2
解决办法
1076
查看次数

C++从成员指针强制转换为持有类指针

我有以下课程:

class SSVec
{
public:
    float values[8];
}
Run Code Online (Sandbox Code Playgroud)

我有一个对象SSVec obj,我将float*指针传递obj.values给另一个函数.在代码的其他地方,我得到这个float*指针,然后用魔杖将它强制转换为SSVec*指针.

这是否可能以C++标准定义的行为方式?大部分时间这都适用于静态演员,但我的猜测是它实际上是未定义的行为.

这样做的原因是float*指针传入和传出DLL,它对SSVec一无所知.我保证传递的指针始终指向SSVec :: value [8]对象成员.

该类可能更复杂,但它不是从任何东西派生,没有虚函数,只包含POD类型.values是第一个成员

问题可以重新制定:班级地址和第一个成员地址是否保证是相同的static_cast

c++ casting class member

4
推荐指数
1
解决办法
334
查看次数

在C ++ Standard中哪里记录了对象的内存布局?

这是一个很大的问题,因此我要求参考而不是小册子大小的答案。我正在进行Stroustrup的C ++之旅,看来对象的布局方式是内存是许多C ++功能设计的基础,例如POD,聚合,带有虚拟成员的类。

不幸的是,Tour本身并没有详细介绍此主题,而对一些标准参考文献(例如C ++ Primer 5ed和TCPPPL 4ed)的ToC进行浏览并不能显示它们是否涉及该主题。

c++ memory-layout language-lawyer object-layout

4
推荐指数
1
解决办法
611
查看次数

C++数组排序

我必须解决一个问题,包括在c ++中对数字列表进行排序.条件是:

  1. 正数,0必须按升序排序
  2. 负数 - 下降

如果A = {4,-8,7,-6,0,-7,5},则最终B = {0,4,5,7,-6,-7,-8}

#include <iostream>
#include <cstring>
using namespace std;
int main()
{
    int i,j,n,A[100],B[100],A_nenegative[100],A_negative[100],aux,m=0,k=0;
    cout<<"max elements"; cin>>n;
    cout<<"elements are"<<endl;
    for(i=0;i<n;i++)
    {
    cin>>A[i];
    }
  for(i=0;i<n;i++)
  for(j=i+1;j<n;j++)
  if(A[i]>A[j])
  {
    aux=A[i];
    A[i]=A[j];
    A[j]=aux;
  }
  for(i = 0; i< n; i++)
    if(A[i]>=0) {
    A_nenegative[i]=A[i];
    B[i]=A_nenegative[i];
    k++;
  }
    for(i=0;i<n;i++)
  for(j=i+1;j<n;j++)
  if(A[i]<A[j])
  {
    aux=A[i];
    A[i]=A[j];
    A[j]=aux;
  }
    for(i=0;i<n;i++)
    if(A[i]<0)
    {
    A_negative[i]=A[i];
    m++;
    }

}
Run Code Online (Sandbox Code Playgroud)

这是我停下来的地方.我在A_negative中对A_nenegative和负数中的正数进行排序.所以问题是如何将B属性首先归结为A_nenegative然后归属于A_negative.我尝试将正数排序后立即归属于B,类似于:

  for(i = 0; i< n; i++)
    if(A[i]>=0) {
    A_nenegative[i]=A[i];
    B[i]=A_nenegative[i];
    k++;
  } …
Run Code Online (Sandbox Code Playgroud)

c++ arrays

-2
推荐指数
1
解决办法
129
查看次数