> On 6 Feb 2018, at 13:23, Lukáš Hrázký <lhra...@redhat.com> wrote: > > On Tue, 2018-02-06 at 12:02 +0100, Christophe de Dinechin wrote: >>> On 25 Jan 2018, at 11:29, Lukáš Hrázký <lhra...@redhat.com> wrote: >>> >>> It's a good practice to consistently use std::string in C++ when there >>> are no special needs for a char *. >> >> OK. Catching up on past e-mail here. FWIW, I disagree with the rationale and >> therefore the change. std::string represents dynamic string. There is no >> reason to use std::string if all you have are text constants. It makes the >> code more verbose and less efficient with no real benefit (see below >> examples in your case). >> >> I really don’t mind much on this specific case, in particular because there >> are actual string computations involved, so it half makes sense in that >> specific case. But let’s not get into the habit of quoting “good practice” >> for bad reasons, i.e. giving the impression that we don’t understand the >> rationale for the good practice being involved. > > Let me rephrase then: I consider it a good practice :) Sorry for > generalizing. > > First, the dynamic allocation/destructor overhead is a premature > optimization beyond critical paths in the code (which fall into the > 'special needs' category mentioned above), so maintainability takes > precedence. > > In this case, maintainability is not an issue either. But in many cases > std::string is a higher level construct that improves maintainability. > And I think it's good to have a consistent usage of std::string, > instead of making a case by case judgement every time and having both > mixed up in the code depending on the author's feeling at the time... > (and then sometimes having to go through code and replace char* with > std::string when the need comes - or leave the code inconsistent) > > That's coming from the C++ side of things. I understand you may have a > different opinion coming from the other side :)
Coming back on-list after an off-list digression discussing this topic with Lukas… Using std::string by default is *not* considered a good practice in C++. The reference for C++ good practices are probably best summarized by the C++ Core Guidelines: https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md. Regarding strings, see https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#Rstr-zstring, which specifically states this: Don't convert a C-style string to string unless there is a reason to. “abc” is a C-style string, even in C++. You should pass it around as const char *, aka czstring as long as you can. *That* is the C++ good practice AFAIK. As an aside, since we are starting to write C++ code, I believe we should add a reference to the C++ Core Guidelines to our style guide, and add it as a bookmark to our browsers. Thanks, Christophe > > Lukas > >>> >>> Signed-off-by: Lukáš Hrázký <lhra...@redhat.com> >>> --- >>> src/concrete-agent.cpp | 10 +++++----- >>> src/concrete-agent.hpp | 4 ++-- >>> src/spice-streaming-agent.cpp | 6 +++--- >>> 3 files changed, 10 insertions(+), 10 deletions(-) >>> >>> diff --git a/src/concrete-agent.cpp b/src/concrete-agent.cpp >>> index 9f1295a..b7d4bfe 100644 >>> --- a/src/concrete-agent.cpp >>> +++ b/src/concrete-agent.cpp >>> @@ -56,11 +56,11 @@ void ConcreteAgent::AddOption(const char *name, const >>> char *value) >>> options.insert(--options.end(), ConcreteConfigureOption(name, value)); >>> } >>> >>> -void ConcreteAgent::LoadPlugins(const char *directory) >>> +void ConcreteAgent::LoadPlugins(const string &directory) >>> { >>> StaticPlugin::InitAll(*this); >>> >>> - string pattern = string(directory) + "/*.so"; >>> + string pattern = directory + "/*.so"; >>> glob_t globbuf; >>> >>> int glob_result = glob(pattern.c_str(), 0, NULL, &globbuf); >>> @@ -77,12 +77,12 @@ void ConcreteAgent::LoadPlugins(const char *directory) >>> globfree(&globbuf); >>> } >>> >>> -void ConcreteAgent::LoadPlugin(const char *plugin_filename) >>> +void ConcreteAgent::LoadPlugin(const string &plugin_filename) >>> { >>> - void *dl = dlopen(plugin_filename, RTLD_LOCAL|RTLD_NOW); >>> + void *dl = dlopen(plugin_filename.c_str(), RTLD_LOCAL|RTLD_NOW); >>> if (!dl) { >>> syslog(LOG_ERR, "error loading plugin %s: %s", >>> - plugin_filename, dlerror()); >>> + plugin_filename.c_str(), dlerror()); >>> return; >>> } >>> >>> diff --git a/src/concrete-agent.hpp b/src/concrete-agent.hpp >>> index 828368b..2449cb3 100644 >>> --- a/src/concrete-agent.hpp >>> +++ b/src/concrete-agent.hpp >>> @@ -30,13 +30,13 @@ public: >>> } >>> void Register(Plugin& plugin) override; >>> const ConfigureOption* Options() const override; >>> - void LoadPlugins(const char *directory); >>> + void LoadPlugins(const std::string &directory); >> >> All use cases are text constants, so not necessary to switch to string. >> >>> // pointer must remain valid >>> void AddOption(const char *name, const char *value); >>> FrameCapture *GetBestFrameCapture(); >>> bool PluginVersionIsCompatible(unsigned pluginVersion) const override; >>> private: >>> - void LoadPlugin(const char *plugin_filename); >>> + void LoadPlugin(const std::string &plugin_filename); >>> std::vector<std::shared_ptr<Plugin>> plugins; >>> std::vector<ConcreteConfigureOption> options; >>> }; >>> diff --git a/src/spice-streaming-agent.cpp b/src/spice-streaming-agent.cpp >>> index f36921d..87e8fa3 100644 >>> --- a/src/spice-streaming-agent.cpp >>> +++ b/src/spice-streaming-agent.cpp >>> @@ -347,13 +347,13 @@ static void cursor_changes(Display *display, int >>> event_base) >>> } >>> >>> static void >>> -do_capture(const char *streamport, FILE *f_log) >>> +do_capture(const string &streamport, FILE *f_log) >>> { >>> std::unique_ptr<FrameCapture> capture(agent.GetBestFrameCapture()); >>> if (!capture) >>> throw std::runtime_error("cannot find a suitable capture system"); >>> >>> - streamfd = open(streamport, O_RDWR); >>> + streamfd = open(streamport.c_str(), O_RDWR); >> >> Example where it makes the text more verbose. >> >>> if (streamfd < 0) >>> // TODO was syslog(LOG_ERR, "Failed to open %s: %s\n", streamport, >>> strerror(errno)); >>> throw std::runtime_error("failed to open streaming device"); >>> @@ -433,7 +433,7 @@ done: >>> >>> int main(int argc, char* argv[]) >>> { >>> - const char *streamport = "/dev/virtio-ports/com.redhat.stream.0"; >>> + string streamport = "/dev/virtio-ports/com.redhat.stream.0”; >> >> This dynamically allocates memory and inserts a destructor call at the end >> of the function, whereas before it was passing a static pointer. >> >>> char opt; >>> const char *log_filename = NULL; >>> int logmask = LOG_UPTO(LOG_WARNING); >>> -- >>> 2.15.1 >>> >>> _______________________________________________ >>> Spice-devel mailing list >>> Spice-devel@lists.freedesktop.org >>> https://lists.freedesktop.org/mailman/listinfo/spice-devel >> >> > _______________________________________________ > Spice-devel mailing list > Spice-devel@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/spice-devel _______________________________________________ Spice-devel mailing list Spice-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/spice-devel