小编Sim*_*ott的帖子

使用静态const而不是#define有什么含义?

gcc抱怨这个:

#include <stdio.h>
static const int YY = 1024;
extern int main(int argc, char*argv[])
{  
  static char x[YY];
}
Run Code Online (Sandbox Code Playgroud)

$ gcc -c test1.c test1.c:在函数main': test1.c:5: error: storage size ofx'中不是常量test1.c:5:错误:变量`x'的大小太大

从x的定义中删除"静态",一切都很好.

我不清楚这里发生了什么:肯定YY 不变的?

我一直认为"静态const"方法比"#define"更可取.在这种情况下有没有办法使用"静态const"?

c

11
推荐指数
2
解决办法
3587
查看次数

从const和返回迭代器的非const方法中删除代码重复

我正在考虑关于const和非const类方法的这个问题.首选答案取自Scott Meyers的Effective C++,其中非const方法是根据const方法实现的.

进一步扩展,如果方法返回迭代器而不是引用,如何减少代码重复?修改链接问题中的示例:

class X
{
    std::vector<Z> vecZ;    
public:
    std::vector<Z>::iterator Z(size_t index)
    {
        // ...
    }
    std::vector<Z>::const_iterator Z(size_t index) const
    {
        // ...
    }
};
Run Code Online (Sandbox Code Playgroud)

我不能在const方法方面实现非const方法,因为不使用distance()/ advance()技术就无法直接从const_iterator转换为迭代器.

在这个例子中,因为我们使用std :: vector作为容器,所以实际上可以从const_iterator转换为迭代器,因为它们很可能被实现为指针.我不想依赖于此.有更通用的解决方案吗?

c++ const dry

9
推荐指数
2
解决办法
1181
查看次数

当mkdir -p不可用时,如何在makefile中创建目录?

我有一个makefile,它通常创建目录:

$(Release_target_OBJDIR)/%.o: %.cpp
     mkdir -p $(dir $@)
     $(COMPILE.cpp) $< $(CFLAGS) $(INCLUDES) -o $@
Run Code Online (Sandbox Code Playgroud)

不幸的是,当我在scratchbox2下运行它时,mkdir -p命令总是无声地失败.

我尝试了以下无效的kludge:

$(Release_target_OBJDIR)/%.o: %.cpp
    mkdir $(dir $(dir $(dir $@)))
    mkdir $(dir $(dir $@))
    mkdir $(dir $@)
    $(COMPILE.cpp) $< $(CFLAGS) $(INCLUDES) -o $@
Run Code Online (Sandbox Code Playgroud)

这输出:

mkdir -p /home/foo/projects/htc/arm/obj/cbar/release/                  
mkdir -p /home/foo/projects/htc/arm/obj/cbar/release/                  
mkdir -p /home/foo/projects/htc/arm/obj/cbar/release/  
Run Code Online (Sandbox Code Playgroud)

...尾部斜杠阻止dir函数以我想要的方式剥离最后一个目录.

如果没有编写脚本或小型C应用程序来复制"-p"功能,是否有人有任何想法在makefile中创建子目录?

如果没有-p选项,当makefile尝试创建已存在的目录时,mkdir将给出错误.我可以做mkdir blah 2>/dev/null但是我冒着失去其他错误消息的风险.

有没有人有任何想法为什么mkdir -p在scratchbox2下不起作用?

编辑

根据bobbogo的建议,我把它放在一起.它看起来相当复杂,但似乎工作,即使在scratchbox2下.

# Generic variables for use in functions
comma:= ,
empty:=
space:= $(empty) $(empty)

# Make directory function
forlooprange = $(wordlist 1,$(words $1),1 2 …
Run Code Online (Sandbox Code Playgroud)

gnu-make mkdir scratchbox

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

迭代封装的嵌套STL容器

这是一个相当普通的STL容器封装,它允许Cfoo的用户迭代容器而不允许更改内部.

#include <vector>

class Cfoo
{
public:
    class Cbar
    {
        /* contents of Cbar */
    };
    typedef std::vector<Cbar> TbarVector;
    typedef TbarVector::const_iterator const_iterator;     
public:
    const_iterator begin() const { return( barVector_.begin() ); }
    const_iterator end() const { return( barVector_.end() ); }
private:
    TbarVector barVector_;
};
Run Code Online (Sandbox Code Playgroud)

到现在为止还挺好.我们可以像这样迭代容器:

Cfoo myFoo;
for (Cfoo::const_iterator it = myFoo.begin(); it != myFoo.end(); ++it)
{
   it->DoSomething();
}
Run Code Online (Sandbox Code Playgroud)

现在我想用一个嵌套的std :: vector替换std :: vector:

public:
    typedef std::vector<Cbar> TbarVectorInner;
    typedef std::vector<TbarVectorInner> TbarVectorOuter;

private:
    TbarVectorOuter barContainer_;
Run Code Online (Sandbox Code Playgroud)

但我希望能够以与以前相同的方式迭代Cbar的所有实例,公开const_iterator,以及begin()const和end()const方法.

我不清楚如何做到这一点,虽然我怀疑它涉及编写自定义迭代器.有什么想法吗?

c++ stl

6
推荐指数
1
解决办法
2132
查看次数

waitpid和pthread_cond_wait(3)

我正在开发一个使用生产者和消费者线程的linux应用程序.这是一个相当成熟的应用程序,我不想更改我的体系结构.

生产者和消费者线程通过可等待的队列链接.这是一个通过std :: queue与条件变量和互斥锁一起实现的类.

现在我希望消费者线程能够分叉/执行子进程,并等到子进程完成,或者等待队列非空,以先发生者为准.如果可等待队列非空,则必须终止子进程.编辑:子进程是无法更改的第三方应用程序.

一种可能性是当子进程终止时在我的条件变量上调用pthread_cond_signal(),但是如何实现呢?我不能使用SIGCHLD的处理程序,至少不能直接使用,因为手册页说pthread_cond_signal()不能从信号处理程序中使用.

一种可能的方法是生成子进程,然后启动一个线程到一个阻塞的waitpid(),最后是pthread_cond_signal().这看起来有点笨拙:我真的需要生成一个线程只是为了关注pid吗?

对于混合waitpid和select/poll/epoll,有Self Pipe Trick.混合waitpid和条件变量有没有相应的东西?

注1:在某些实现中,SIGCHLD中断条件变量等待函数.这是不可移植的,如果可能的话,我宁愿不依赖这种行为.

注意2:由于条件变量封装在可等待的队列类中,我需要扩展此类以允许应用程序发出互斥锁信号.这只是一个简单的实现细节,我在我的问题中掩盖了这一点.

c++ linux pthreads

6
推荐指数
1
解决办法
496
查看次数

C ++设计:从基类转换为派生类,没有额外的数据成员

我写了很多处理消息协议的代码。消息协议通常会具有通用的消息帧,可以从串行端口或套接字反序列化。该帧包含消息类型,并且必须根据消息类型来处理消息有效负载。

通常,我用访问器方法和构造函数编写一个多态类集,该构造函数引用消息框。

我想到的是,我可以直接从消息框架派生访问器类,然后从消息框架重新解释_cast到适当的访问器类,而不是基于对消息框架的引用来构造访问器类。这使代码更加简洁,并节省了一些字节和处理器周期。

请参见下面的示例(极度虚构和压缩)。显然,对于生产代码,所有这些都需要适当地封装,强制转换成为派生类的成员,更好地分离了所关注的问题,并添加了一些验证。为了简洁起见,已全部删除。

#include <iostream>
#include <cstring>
#include <vector>

struct GenericMessage
{
  GenericMessage(const char* body):body_(body, body+strlen(body)){}
  std::vector<char> body_;  
};

struct MessageType1:public GenericMessage
{
    int GetFoo()const
    {
        return body_[2];
    }
    int GetBar()const
    {
        return body_[3];
    }    
};

int main() 
{
    GenericMessage myGenericMessage("1234");
    MessageType1* myMgessageType1 = reinterpret_cast<MessageType1*>(&myGenericMessage);
    std::cout << "Foo:" << myMgessageType1->GetFoo() << std::endl;
    std::cout << "Bar:" << myMgessageType1->GetBar() << std::endl;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我从来没有见过任何地方这样做。考虑到派生没有其他数据成员,以这种方式从基础到派生有任何不利之处吗?

c++ inheritance

6
推荐指数
1
解决办法
1376
查看次数

boost :: filesystem :: rename:该文件已经存在时无法创建该文件

我正在使用boost :: filesystem重命名文件,有时目标文件将存在。根据此处的升压文档:

http://www.boost.org/doc/libs/1_42_0/libs/filesystem/doc/reference.html#Non-member-functions

模板无效重命名(const Path1&from_p,const Path2&to_p); 要求:Path1 :: external_string_type和Path2 :: external_string_type是同一类型。

效果:将from_p重命名为to_p,就像通过POSIX named()一样。

后置条件:!exists(from_p)&&存在(to_p),否则原先名为from_p的文件的内容和属性不变。

[注意:如果from_p和to_p解析为同一文件,则不执行任何操作。否则,如果to_p解析为现有文件,则将其删除。符号链接本身会重命名,而不是解析为重命名的文件。-尾注]

(我的重点)

在XP SP3上测试通过MS Visual Studio 2008编译的代码时,重命名会引发boost :: filesystem :: filesystem_error并显示以下消息:

该文件已存在时无法创建该文件

我注意到这是在错误报告中提出的:https : //svn.boost.org/trac/boost/ticket/2866

...但是声称在Boost 1.41.0中已关闭,而我正在使用Boost 1.42.0。

我在这里做错了还是应该恢复为std :: rename?

我还没有在Linux上测试过它,所以也不知道问题是否也存在。

c++ filesystems boost

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

如何在gnu make中拆分路径名?

在GNU Make中,我需要获取运行makefile的目录的父目录的名称.

例如,如果makefile是/ home/fnord/foo/bar/Makefile,我想将变量设置为字符串"foo".

我可以使用一些GNU Make内置函数来实现这一点,为了清楚起见,这里显示了所有这些功能.

V1=$(CURDIR)
V2=$(dir $(V1))
V3=$(subst /, ,$(V2))
V4=$(lastword $(V3))
Run Code Online (Sandbox Code Playgroud)

对于这样一个简单的要求,这似乎很复杂,但我找不到更好的方法.有没有更好的技术来分割GNU Make中的路径名?

我需要这个在GNU Make 3.81及更高版本中工作.

gnu-make

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

从旧的Subversion备份中恢复文件

我有一个来自旧的颠覆服务器的tar备份,该服务器早已死亡.由此服务器管理的所有源代码都是遗留代码,除了这个项目之外,它将永远不再需要.

tar文件中充满了像"conf","dav","db"这样的小目录......

有没有办法从这个备份中提取单个项目的最终源代码?

svn

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

在多个应用程序之间共享内存 SQLite 数据库

可以创建内存中的 SQlite 数据库:

rc = sqlite3_open(":memory:", &db);
Run Code Online (Sandbox Code Playgroud)

但如果我理解了文档,那么该数据库对于创建它的应用程序来说是本地的。

我需要一个可以由多个应用程序访问的内存 SQLite 数据库。除了在虚拟磁盘上创建数据库之外,还有其他方法吗?

这是针对嵌入式Linux 平台的。

c sqlite

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

标签 统计

c++ ×5

c ×2

gnu-make ×2

boost ×1

const ×1

dry ×1

filesystems ×1

inheritance ×1

linux ×1

mkdir ×1

pthreads ×1

scratchbox ×1

sqlite ×1

stl ×1

svn ×1